feat: expand cockpit integrations and support workflows

Add Phoenix remote desktop, action connector, documentation engine, and gamification support. Refactor support-case processing and search/action UI, and update installer assets and dependencies.
This commit is contained in:
Meik
2026-07-13 11:16:53 +02:00
parent bbedbf71c8
commit 0b52999b1d
303 changed files with 11235 additions and 3580 deletions

View File

@@ -29,7 +29,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.2" newVersion="10.0.0.2" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.3" newVersion="10.0.0.3" />
</dependentAssembly>
</assemblyBinding>
</runtime>

View File

@@ -506,13 +506,14 @@ namespace FasdDesktopUi
closeUserSessionTask = cFasdCockpitCommunicationBase.Instance?.CloseUserSession(cFasdCockpitConfig.SessionId).ConfigureAwait(false);
}
await cFasdCockpitCommunicationBase.Instance?.TerminateAsync();
if (cFasdCockpitCommunicationBase.Instance != null)
await cFasdCockpitCommunicationBase.Instance?.TerminateAsync();
if (notifyIcon != null)
{
try
{
cConnectionStatusHelper.Instance.IsActive = false;
cConnectionStatusHelper.Instance.ApplicationIsExiting = true;
notifyIcon.Visible = false;
notifyIcon.Dispose();
cAppStartUp.Terminate();

View File

@@ -30,6 +30,8 @@ using C4IT.MultiLanguage;
using C4IT.F4SD.TAPI;
using static C4IT.Logging.cLogManager;
using F4SD.Gamification.Services;
using F4SD.Gamification;
namespace FasdDesktopUi
@@ -48,6 +50,9 @@ namespace FasdDesktopUi
LogMethodBegin(CM);
try
{
GamificationService.Initialize();
LevelService.LevelChanged += HandleLevelChanged;
#if isDemo
cFasdCockpitCommunicationBase.Instance = new cFasdCockpitCommunicationDemo();
#else
@@ -91,6 +96,7 @@ namespace FasdDesktopUi
}
finally
{
splashScreen?.Hide();
LogMethodEnd(CM);
}
@@ -98,6 +104,20 @@ namespace FasdDesktopUi
return false;
}
private static void HandleLevelChanged(object sender, LevelEventArgs e)
{
if (e.CurrentLevel <= 1 || !cFasdCockpitConfig.Instance.Global.UseGamification)
return;
Dispatcher.CurrentDispatcher.Invoke(async () =>
{
Pages.LevelUpPage.LevelUpPage levelUpWindow = new Pages.LevelUpPage.LevelUpPage();
levelUpWindow.NewLevel = e.CurrentLevel;
levelUpWindow.LevelTitle = e.LevelTitle;
levelUpWindow.Show();
});
}
public static bool ProcessCommandLine(string[] Args)
{
var CM = MethodBase.GetCurrentMethod();
@@ -669,11 +689,11 @@ namespace FasdDesktopUi
{
userInfo = cFasdCockpitCommunicationBase.CockpitUserInfo;
}
if (cFasdCockpitConfig.Instance.HasM42Configuration())
if (userInfo?.possibleLogons != null)
{
if (userInfo.possibleLogons.Contains(enumAdditionalAuthentication.M42WinLogon))
{
if (cFasdCockpitConfig.Instance.HasM42Configuration())
if (userInfo?.possibleLogons != null)
{
if (userInfo.possibleLogons.Contains(enumAdditionalAuthentication.M42WinLogon))
{
if (App.M42OptionMenuItem != null)
{
App.M42OptionMenuItem.Visible = true;

View File

@@ -0,0 +1,27 @@
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
namespace FasdDesktopUi.Basics.Converter
{
[ValueConversion(typeof(string), typeof(XmlLanguage))]
internal class LanguageCultureConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is string tag))
return Binding.DoNothing;
return XmlLanguage.GetLanguage(tag);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is XmlLanguage lang))
return Binding.DoNothing;
return lang.IetfLanguageTag;
}
}
}

View File

@@ -31,7 +31,7 @@ namespace FasdDesktopUi.Basics
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 parameter = new cF4SDServerQuickActionParameters() { Action = ServerAction.Action, Category = ServerAction.Category, ParameterType = ServerAction.ParameterType, Identities = dataProvider.Identities, AdjustableParameter = ParameterDictionary };
var payload = JsonConvert.SerializeObject(parameter);
var result = await http.PostJsonAsync("api/QuickAction/Run", payload, 15000, CancellationToken.None);

View File

@@ -0,0 +1,126 @@
using C4IT.FASD.Base;
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Models;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.Helper
{
internal static class ActionDisplayTypeInspector
{
internal static enumActionDisplayType GetDisplayType(cFasdBaseConfigMenuItem menuDataDefinition, cNamedParameterList namedParameterEntries, IEnumerable<enumFasdInformationClass> availableInformationClasses)
{
if (menuDataDefinition.IsHidden)
return enumActionDisplayType.hidden;
else if (IsEnabled(menuDataDefinition, namedParameterEntries, availableInformationClasses))
return enumActionDisplayType.enabled;
else
return enumActionDisplayType.disabled;
}
private static bool IsEnabled(cFasdBaseConfigMenuItem menuDataDefinition, cNamedParameterList namedParameterEntries, IEnumerable<enumFasdInformationClass> availableInformationClasses)
{
if (!HasRequiredInformationClasses(menuDataDefinition, availableInformationClasses))
return false;
if (menuDataDefinition is cFasdQuickAction quickActionDefinition && !IsQuickActionEnabled(quickActionDefinition, namedParameterEntries))
return false;
else
return true;
}
private static bool IsQuickActionEnabled(cFasdQuickAction quickActionDefinition, cNamedParameterList namedParameterEntries)
{
if (!string.IsNullOrEmpty(quickActionDefinition.CheckFilePath) && !FileExists(quickActionDefinition.CheckFilePath))
return false;
if (!string.IsNullOrEmpty(quickActionDefinition.CheckRegistryEntry) && !RegistryEntryExists(quickActionDefinition.CheckRegistryEntry))
return false;
if (namedParameterEntries is null)
return true;
cNamedParameterEntryBase namedParameterValue = null;
if (!string.IsNullOrEmpty(quickActionDefinition.CheckNamedParameter) && !namedParameterEntries.TryGetValue(quickActionDefinition.CheckNamedParameter, out namedParameterValue))
return false;
if (namedParameterValue != null && quickActionDefinition.CheckNamedParameterValues != null && !quickActionDefinition.CheckNamedParameterValues.Contains(namedParameterValue.GetValue()))
return false;
return true;
}
private static bool HasRequiredInformationClasses(cFasdBaseConfigMenuItem definition, IEnumerable<enumFasdInformationClass> availableInformationClasses)
{
if (definition?.InformationClasses is null)
return true;
if (definition.InformationClasses.Count == 0)
return true;
if (definition.InformationClasses.Any(i => !availableInformationClasses.Contains(i)))
return false;
return true;
}
private static bool FileExists(string path)
{
try
{
if (string.IsNullOrWhiteSpace(path))
return true;
var specialFolders = Enum.GetValues(typeof(Environment.SpecialFolder)).Cast<Environment.SpecialFolder>();
foreach (var specialFolder in specialFolders)
{
string specialFolderName = $"%{specialFolder}%";
string specialFolderPath = Environment.GetFolderPath(specialFolder);
path = path.Replace(specialFolderName, specialFolderPath);
}
path = Environment.ExpandEnvironmentVariables(path);
return File.Exists(path);
}
catch (Exception E)
{
LogException(E);
return false;
}
}
private static bool RegistryEntryExists(string entry)
{
try
{
if (string.IsNullOrWhiteSpace(entry))
return true;
string rootPath = entry.Split('\\')[0];
entry = entry.Replace(rootPath, "").Remove(0, 1);
switch (rootPath)
{
case "HKEY_LOCAL_MACHINE":
case "HKLM":
return Registry.LocalMachine.OpenSubKey(entry) != null;
case "HKEY_CURRENT_USER":
case "HKCU":
return Registry.CurrentUser.OpenSubKey(entry) != null;
default:
return false;
}
}
catch (Exception E)
{
LogException(E);
return false;
}
}
}
}

View File

@@ -7,7 +7,6 @@ using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using C4IT.Configuration;
using C4IT.F4SD.DisplayFormatting;
@@ -27,7 +26,6 @@ using FasdDesktopUi.Pages.SlimPage.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using static C4IT.FASD.Base.cF4SDHealthCardRawData;
using static C4IT.Logging.cLogManager;
@@ -80,7 +78,7 @@ namespace FasdDesktopUi.Basics.Helper
{
this.dataProvider = dataProvider;
_menuDataProvider = new MenuItemDataProvider(dataProvider);
cUtility.RawValueFormatter.SetDefaultCulture(new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
cUtility.RawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
HistoryData = new cHealthCardHistoryDataHelper(this);
@@ -149,7 +147,7 @@ namespace FasdDesktopUi.Basics.Helper
if (informationClasses is null)
return null;
foreach (var healthCard in cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.HealthCards.Values)
foreach (var healthCard in cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.HealthCards?.Values)
{
bool found = true;
@@ -250,7 +248,7 @@ namespace FasdDesktopUi.Basics.Helper
{
List<object> output = new List<object>();
if (healthCardColumn?.Values == null)
if (healthCardColumn?.Values == null || startingIndex < 0)
return output;
try
@@ -453,13 +451,9 @@ namespace FasdDesktopUi.Basics.Helper
var stateValue = GetStateValueAt(stateDefinition.DatabaseInfo, dayIndex, isStatic);
enumHighlightColor? tempColor = null;
if (stateValue != null)
{
tempColor = GetHighlightColor(stateValue, stateDefinition, dayIndex, isStatic);
if (tempColor == enumHighlightColor.none && stateValue != null)
tempColor = enumHighlightColor.green;
}
enumHighlightColor? tempColor = GetHighlightColor(stateValue, stateDefinition, dayIndex, isStatic);
if (tempColor == enumHighlightColor.none && stateValue != null)
tempColor = enumHighlightColor.green;
if (output == null)
output = tempColor;
@@ -492,7 +486,7 @@ namespace FasdDesktopUi.Basics.Helper
}
else
{
FormattingOptions options = new FormattingOptions() { ReferenceDate = DateTime.UtcNow.Date.AddDays(columnIndex), TimeZone = TimeZoneInfo.Local };
FormattingOptions options = new FormattingOptions() { ReferenceDate = DateTime.UtcNow.Date.AddDays(-columnIndex), TimeZone = TimeZoneInfo.Local };
var _c = cUtility.RawValueFormatter.GetDisplayValue(value, Requirements.valueState.DisplayType, options);
if (!string.IsNullOrWhiteSpace(_c))
cellContent.Content = _c;
@@ -689,11 +683,19 @@ namespace FasdDesktopUi.Basics.Helper
{
if (NamedParameters == null)
return false;
var _invert = false;
if (namedParameter.StartsWith("!"))
{
_invert = true;
namedParameter = namedParameter.Remove(0, 1);
}
if (!NamedParameters.TryGetValue(namedParameter, out var entry))
return false;
return _invert;
var entryValue = entry.GetValue();
cConfigRegistryHelper.ReadFromStringBoolean(entryValue, out var result);
if (_invert)
result = !result;
return result;
}
@@ -1113,11 +1115,14 @@ namespace FasdDesktopUi.Basics.Helper
}
}
const string defaultCopyTemplateParameterName = "Copy_default";
if (!dataProvider.NamedParameterEntries.ContainsKey(defaultCopyTemplateParameterName))
{
string defaultCopyTemplate = cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate.Name;
dataProvider.NamedParameterEntries.Add(defaultCopyTemplateParameterName, new cNamedParameterEntryCopyTemplate(dataProvider, defaultCopyTemplate));
dataProvider.NamedParameterEntries.Add(defaultCopyTemplateParameterName, new cNamedParameterEntryCopyTemplate(dataProvider, SelectedHealthCard.DefaultCopyTemplate != null ? SelectedHealthCard.DefaultCopyTemplate : defaultCopyTemplate));
}
foreach (var copyTemplate in cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.CopyTemplates)
@@ -1202,8 +1207,8 @@ namespace FasdDesktopUi.Basics.Helper
var historySectionValueColumns = new List<DetailsPageDataHistoryColumnModel>(valueColumnCount);
for (int i = 0; i < valueColumnCount; i++)
{
CultureInfo culture = new CultureInfo(cMultiLanguageSupport.CurrentLanguage);
var valueColumnHeader = i != 0 ? DateTime.Today.AddDays(-i).ToString(cMultiLanguageSupport.GetItem("Global.Date.Format.ShortDateWithDay", "ddd. dd.MM."), culture) : cMultiLanguageSupport.GetItem("Global.Date.Today");
CultureInfo culture = cFasdCockpitConfig.Instance.SelectedCulture;
var valueColumnHeader = i != 0 ? DateTime.Today.AddDays(-i).ToString($"ddd. {cUtility.GetShortDatePattern()}") : cMultiLanguageSupport.GetItem("Global.Date.Today");
var summaryStatusColor = parent.GetSummaryStatusColor(stateCategoryDefinition.States, false, i);
var valueColumn = new DetailsPageDataHistoryColumnModel() { ColumnValues = new List<cDataHistoryValueModel>(), Content = valueColumnHeader, HighlightColor = summaryStatusColor ?? enumHighlightColor.none };
historySectionValueColumns.Add(valueColumn);
@@ -2165,6 +2170,7 @@ namespace FasdDesktopUi.Basics.Helper
bool isDataIncomplete = true;
await LoadingRawDataCriticalSection.EnterAsync();
try
{
lock (HealthCardRawData)

View File

@@ -1,6 +1,7 @@
using C4IT.FASD.Base;
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.SupportCase.Processors;
using FasdDesktopUi.Basics.UiActions;
using Microsoft.Win32;
using System;
@@ -15,7 +16,6 @@ namespace FasdDesktopUi.Basics.Helper
internal class MenuItemDataProvider
{
private readonly cSupportCaseDataProvider _dataProvider;
private const int defaultPinnedActionCount = 3; //search, notepad, copyTicketInformation
public MenuItemDataProvider(cSupportCaseDataProvider dataProvider)
@@ -58,7 +58,7 @@ namespace FasdDesktopUi.Basics.Helper
return menuItemData;
}
private cMenuDataBase GetMenuItem(cFasdBaseConfigMenuItem menuItemConfig)
internal cMenuDataBase GetMenuItem(cFasdBaseConfigMenuItem menuItemConfig)
{
try
{
@@ -81,7 +81,7 @@ namespace FasdDesktopUi.Basics.Helper
if (menuItem != null)
{
if (!cHealthCardDataHelper.IsUiVisible(menuItemConfig, _dataProvider.NamedParameterEntries))
if (_dataProvider != null && !cHealthCardDataHelper.IsUiVisible(menuItemConfig, _dataProvider.NamedParameterEntries))
menuItem.SetUiActionDisplayType(enumActionDisplayType.hidden);
}
return menuItem;
@@ -129,7 +129,7 @@ namespace FasdDesktopUi.Basics.Helper
}
private bool HasAllRequirements(cFasdQuickAction quickAction)
internal bool HasAllRequirements(cFasdQuickAction quickAction)
{
try
{
@@ -137,9 +137,14 @@ namespace FasdDesktopUi.Basics.Helper
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())));
bool hasRequiredNamedParameter = true;
if (_dataProvider != null)
{
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;

View File

@@ -1,13 +1,17 @@
using System;
using System.Collections.Generic;
using C4IT.FASD.Base;
using C4IT.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using C4IT.FASD.Base;
using C4IT.Logging;
using FasdDesktopUi.Basics;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.Helper
{
internal static class TicketDeepLinkHelper
internal static class TicketExternalLinkHelper
{
internal static bool TryOpenTicketRelationExternally(cF4sdApiSearchResultRelation relation)
{
@@ -16,127 +20,51 @@ namespace FasdDesktopUi.Basics.Helper
if (relation == null || relation.Type != enumF4sdSearchResultClass.Ticket)
return false;
var ticketConfig = cFasdCockpitConfig.Instance?.Global?.TicketConfiguration;
if (ticketConfig == null)
// check how we should open this ticket (intern, extern or both)
var ticketType = GetTicketType(relation);
var processing = ShouldOpenExternally(ticketType);
// check if we have a valid user id in the id list => if not we could open this ticket only extern.
var hasUser = relation.Identities.Any(e => (e.Class == enumFasdInformationClass.User && e.Id != null && e.Id != Guid.Empty));
if (!hasUser)
processing = enumTicketProcessing.Extern;
if (processing == enumTicketProcessing.Intern)
return false;
var activityType = GetActivityType(relation);
var openExternally = ShouldOpenExternally(ticketConfig, activityType);
if (!openExternally)
return false;
var url = BuildTicketDeepLink(relation.id, activityType);
if (string.IsNullOrWhiteSpace(url))
return false;
if (relation?.Infos?.TryGetValue("TicketLink", out var ticketLink) == true && !string.IsNullOrWhiteSpace(ticketLink))
new cBrowsers().Start("default", ticketLink);
new cBrowsers().Start("default", url);
return true;
return processing == enumTicketProcessing.Extern;
}
catch (Exception ex)
{
LogException(ex);
}
return false;
}
private static string GetActivityType(cF4sdApiSearchResultRelation relation)
{
if (relation?.Infos != null && relation.Infos.TryGetValue("ActivityType", out var activityTypeValue))
return activityTypeValue;
return null;
}
private static bool ShouldOpenExternally(cF4sdTicketConfig ticketConfig, string activityType)
{
if (ticketConfig == null)
return false;
if (TryGetOverride(ticketConfig.OpenActivitiesExternallyOverrides, activityType, out var overrideValue))
return overrideValue;
return ticketConfig.OpenActivitiesExternally;
}
private static bool TryGetOverride(IEnumerable<string> overrides, string activityType, out bool value)
{
value = false;
if (string.IsNullOrWhiteSpace(activityType) || overrides == null)
return false;
foreach (var entry in overrides)
{
if (string.IsNullOrWhiteSpace(entry))
continue;
var parts = entry.Split(new[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2)
continue;
var typeName = parts[0].Trim();
if (!string.Equals(typeName, activityType, StringComparison.OrdinalIgnoreCase))
continue;
if (!TryParseBool(parts[1], out value))
return false;
return true;
}
return false;
}
private static bool TryParseBool(string value, out bool result)
{
result = false;
if (string.IsNullOrWhiteSpace(value))
return false;
switch (value.Trim().ToLowerInvariant())
{
case "true":
case "1":
case "yes":
result = true;
return true;
case "false":
case "0":
case "no":
result = false;
return true;
default:
return bool.TryParse(value, out result);
}
}
return false;
}
internal static string BuildTicketDeepLink(Guid ticketId, string activityType)
private static enumTicketType GetTicketType(cF4sdApiSearchResultRelation relation)
{
if (ticketId == Guid.Empty)
return null;
var server = cCockpitConfiguration.Instance?.m42ServerConfiguration?.Server;
if (string.IsNullOrWhiteSpace(server))
return null;
var baseUrl = server.TrimEnd('/');
if (!baseUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
!baseUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
if (relation?.Infos != null && relation.Infos.TryGetValue("TicketType", out var ticketTypeValue))
{
baseUrl = "https://" + baseUrl;
if (Enum.TryParse<enumTicketType>(ticketTypeValue, true, out var ticketType))
return ticketType;
}
if (!baseUrl.EndsWith("/wm", StringComparison.OrdinalIgnoreCase))
baseUrl += "/wm";
return enumTicketType.Ticket;
}
if (string.IsNullOrWhiteSpace(activityType))
return null;
private static enumTicketProcessing ShouldOpenExternally(enumTicketType ticketType)
{
var ticketConfig = cFasdCockpitConfig.Instance?.Global?.TicketConfiguration;
if (ticketConfig == null)
return enumTicketProcessing.Extern;
var viewOptionsJson = $"{{\"embedded\":false,\"objectId\":\"{ticketId}\",\"type\":\"{activityType}\",\"viewType\":\"preview\",\"archived\":0}}";
var viewOptionsEncoded = Uri.EscapeDataString(viewOptionsJson);
if (ticketConfig.TicketProcessing?.TryGetValue(ticketType, out var processing) == true)
return processing;
return $"{baseUrl}/app-ServiceDesk/?view-options={viewOptionsEncoded}";
return ticketConfig.DefaultProcessing;
}
}
}

View File

@@ -48,7 +48,9 @@ namespace FasdDesktopUi.Basics.Models
heartBeat
}
public bool IsActive = true;
public enumOnlineStatus ApiConnectionStatus { get; private set; } = enumOnlineStatus.notSpecified;
public bool ApplicationIsExiting { get; set; } = false;
public readonly Version MinServerVersion = new Version("0.0.0.0");
@@ -64,16 +66,15 @@ namespace FasdDesktopUi.Basics.Models
public static cConnectionStatusHelper Instance { get; set; }
public bool IsAuthorizationSupported { get; private set; } = false;
private bool IsAuthorizationSupported { get; set; } = false;
private System.Timers.Timer timer;
#region Lock Elements Connecion Status
private readonly object connectionStatusCheckLock = new object();
private enumCheckRunning IsConnectionStatusCheckRunning = enumCheckRunning.no;
private int OnlineCheckCounter = 0;
#endregion
public enumOnlineStatus ApiConnectionStatus = enumOnlineStatus.notSpecified;
public cConnectionStatusHelper()
{
ApiConnectionStatus = enumOnlineStatus.offline;
@@ -125,44 +126,47 @@ namespace FasdDesktopUi.Basics.Models
return (timerInterval, shortInterval);
}
private void HandleConnectionStatus(enumConnectionStatus status, ref int timerInterval, int timerInteralShort)
private enumOnlineStatus HandleConnectionStatus(enumConnectionStatus status, ref int timerInterval, int timerInteralShort)
{
var newStatus = ApiConnectionStatus;
switch (status)
{
case enumConnectionStatus.unknown:
case enumConnectionStatus.serverNotFound:
if (ApiConnectionStatus != enumOnlineStatus.offline)
ApiConnectionStatus = enumOnlineStatus.offline;
if (newStatus != enumOnlineStatus.offline)
newStatus = enumOnlineStatus.offline;
timerInterval = timerInteralShort;
LogEntry("RunConnectionStatusCheckAsync: Exit due to status 'serverNotFound'");
break;
case enumConnectionStatus.serverResponseError:
ApiConnectionStatus = enumOnlineStatus.connectionError;
newStatus = 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;
newStatus = enumOnlineStatus.incompatibleServerVersion;
break;
case enumConnectionStatus.serverStarting:
ApiConnectionStatus = enumOnlineStatus.serverStarting;
newStatus = enumOnlineStatus.serverStarting;
break;
case enumConnectionStatus.serverNotConfigured:
ApiConnectionStatus = enumOnlineStatus.serverNotConfigured;
newStatus = enumOnlineStatus.serverNotConfigured;
break;
case enumConnectionStatus.connected:
if (cCockpitConfiguration.Instance == null || cF4SDCockpitXmlConfig.Instance == null)
ApiConnectionStatus = enumOnlineStatus.illegalConfig;
newStatus = enumOnlineStatus.illegalConfig;
else if (ApiConnectionStatus != enumOnlineStatus.online)
ApiConnectionStatus = enumOnlineStatus.online;
newStatus = enumOnlineStatus.online;
break;
}
return newStatus;
}
public async Task RunConnectionStatusCheckAsync(SplashScreenView splashScreen)
{
if (!IsActive)
if (ApplicationIsExiting)
return;
var CM = MethodBase.GetCurrentMethod();
@@ -195,7 +199,7 @@ namespace FasdDesktopUi.Basics.Models
cCheckConnectionResult connectionResult = await cFasdCockpitCommunicationBase.Instance.CheckConnection(MinServerVersion);
IsAuthorizationSupported = connectionResult?.ApiConnectionInfo?.SupportAuthorisation ?? false;
HandleConnectionStatus(connectionResult.ConnectionStatus, ref timerInterval, shortTimerInterval);
ApiConnectionStatus = HandleConnectionStatus(connectionResult.ConnectionStatus, ref timerInterval, shortTimerInterval);
if (connectionResult.ConnectionStatus != enumConnectionStatus.connected)
return;
@@ -210,7 +214,12 @@ namespace FasdDesktopUi.Basics.Models
var configTasks = await Task.WhenAll(loadConfigFilesTask, getCockpitConfig);
if (configTasks.Any(t => t == false))
{
LogEntry("Connection status check wasn't successfull. Could not retrieve all configurations.", LogLevels.Warning);
await Task.Delay(TimeSpan.FromSeconds(5));
await RunConnectionStatusCheckAsync(splashScreen);
return;
}
if (cFasdCockpitConfig.Instance?.Global != null && cCockpitConfiguration.Instance?.GlobalConfig != null)
{
cFasdCockpitConfig.Instance.Global.Load(cCockpitConfiguration.Instance.GlobalConfig);
@@ -225,33 +234,34 @@ namespace FasdDesktopUi.Basics.Models
}
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";
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
if (userInfo is null || DateTime.UtcNow > userInfo.RenewUntil)
{
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 (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
@@ -280,9 +290,9 @@ namespace FasdDesktopUi.Basics.Models
}
if (App.M42OptionMenuItem != null)
App.Current.MainWindow.Dispatcher.Invoke(() =>
Dispatcher.CurrentDispatcher.Invoke(() =>
{
App.M42OptionMenuItem.Enabled = userInfo != null;
App.M42OptionMenuItem.Enabled = userInfo != null;
});
// check, if the are logons needed
@@ -291,6 +301,7 @@ namespace FasdDesktopUi.Basics.Models
await cFasdCockpitConfig.Instance.CheckServerQuickActionAvailabilityAsync();
await cFasdCockpitCommunicationBase.Instance.InitializeAfterOnlineAsync();
cFasdCockpitConfig.Instance.OnUiSettingsChanged();
await Task.Run(async () => await cFasdCockpitConfig.Instance.InstantiateAnalyticsAsync(cFasdCockpitConfig.SessionId));
}
catch (Exception E)
{
@@ -312,7 +323,7 @@ namespace FasdDesktopUi.Basics.Models
LogException(E);
}
if (IsActive)
if (!ApplicationIsExiting)
{
if (ApiConnectionStatus == enumOnlineStatus.online)
NotifyerSupport.SetNotifyIcon("Default", null, NotifyerSupport.enumIconAlignment.BottomRight);
@@ -334,6 +345,7 @@ namespace FasdDesktopUi.Basics.Models
}
finally
{
OnlineCheckCounter++;
LogMethodEnd(CM);
}
}

View File

@@ -0,0 +1,175 @@
using C4IT.FASD.Base;
using F4SD_AdaptableIcon;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Converter;
using FasdDesktopUi.Basics.UiActions;
using System;
using System.Collections.Generic;
namespace FasdDesktopUi.Basics.Models.DTOs
{
// __ __ ____ ____
// | |__| || || \
// | | | | | | | o )
// | | | | | | | _/
// | ` ' | | | | |
// \ / | | | |
// \_/\_/ |____||__|
// the following classes are work in Progress and shouldn't been used
[Obsolete]
internal readonly struct IconInfo
{
public IconData? Overlay { get; }
public double IconScale { get; }
public bool IsInactive { get; }
public string Description { get; }
public IconInfo(bool isInactive = default, string description = null, IconData? overlay = null, double iconScale = 1.0)
{
Overlay = overlay;
IsInactive = isInactive;
Description = description;
IconScale = iconScale;
}
}
[Obsolete]
internal abstract class MenuDataBaseDto
{
private readonly IconData _icon;
public string Title { get; set; }
public string SubTitle { get; set; }
public cUiActionBase Action { get; set; }
public IconInfo IconInformation { get; set; }
public int PositoinIndex { get; set; }
protected MenuDataBaseDto() { }
protected MenuDataBaseDto(cFasdBaseConfigMenuItem menuItemDefinition)
{
_icon = IconDataConverter.Convert(menuItemDefinition.Icon);
Title = menuItemDefinition.Names.GetValue();
}
internal virtual IconData GetIcon() => _icon;
}
[Obsolete]
internal sealed class ContainerMenuDataDto : MenuDataBaseDto
{
public IList<MenuDataBaseDto> SubMenuData { get; set; } = new List<MenuDataBaseDto>();
public ContainerMenuDataDto(cFasdMenuSection sectionDefintion) : base(sectionDefintion)
{
Action = new cSubMenuAction(true); // todo rework subMenuAction
}
}
[Obsolete]
internal sealed class LoadingMenuDataDto : MenuDataBaseDto
{
private readonly IconData _icon = new IconData(enumInternGif.loadingSpinner);
public LoadingMenuDataDto(string loadingText)
{
Title = loadingText;
}
internal override IconData GetIcon() => _icon;
}
[Obsolete]
internal sealed class SearchResultMenuDataDto : MenuDataBaseDto
{
private readonly cFasdApiSearchResultEntry _searchResultEntry;
public enumF4sdSearchResultClass Type { get => _searchResultEntry.Type; }
public SearchResultMenuDataDto(cFasdApiSearchResultEntry searchResultEntry)
{
_searchResultEntry = searchResultEntry;
//Action = new cUiProcessSearchRelationAction()
}
internal override IconData GetIcon()
{
switch (Type)
{
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:
break;
case enumF4sdSearchResultClass.VirtualSession:
break;
case enumF4sdSearchResultClass.MobileDevice:
break;
default:
break;
}
throw new NotImplementedException();
}
}
[Obsolete]
internal sealed class SearchRelationMenuDataDto : MenuDataBaseDto
{
private readonly cF4sdApiSearchResultRelation _searchRelation;
public enumF4sdSearchResultClass Type { get => _searchRelation.Type; }
public DateTime LastUsed { get; private set; }
public double UsingFactor { get; private set; }
public Dictionary<string, string> AdditionalInfos { get; private set; } // todo check
public bool IsUsedForCaseEnrichtment { get; set; } // todo check
public string TrailingText { get; set; }
public SearchRelationMenuDataDto(cF4sdApiSearchResultRelation searchRelation)
{
_searchRelation = searchRelation;
//Action = new cUiProcessSearchRelationAction()
}
internal override IconData GetIcon()
{
throw new NotImplementedException();
}
}
[Obsolete]
internal sealed class QuickActionMenuDataDto : MenuDataBaseDto
{
public QuickActionMenuDataDto(cFasdQuickAction quickActionDefinition) : base(quickActionDefinition)
{
Action = cUiActionBase.GetUiAction(quickActionDefinition);
}
}
[Obsolete]
internal sealed class QuickTipMenuDataDto : MenuDataBaseDto
{
public QuickTipMenuDataDto(cFasdQuickTip quickTipDefinition) : base(quickTipDefinition)
{
Title = quickTipDefinition.Names.GetValue();
Action = new cUiQuickTipAction(quickTipDefinition);
}
}
[Obsolete]
internal sealed class CopyTemplateMenuDataDto : MenuDataBaseDto
{
public CopyTemplateMenuDataDto(cCopyTemplate copyActionDefintion) : base(copyActionDefintion)
{
Action = new cUiCopyAction(copyActionDefintion);
}
}
}

View File

@@ -119,6 +119,9 @@ namespace FasdDesktopUi.Basics.Models
{
try
{
if (actionSteps is null)
return;
foreach (var step in actionSteps)
{
if (step.StepType.Equals(type) && step.QuickActionName.Equals(quickActionName))

View File

@@ -1,199 +1,292 @@
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();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
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 MenuIconInfo 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 class MenuIconInfo
{
public readonly IconData Icon;
public readonly IconData? Overlay;
public readonly bool IsInactive;
public readonly string Description;
public MenuIconInfo(IconData icon, string Description = null, bool isInactive = false, IconData? overlay = null)
{
Icon = icon;
IsInactive = isInactive;
this.Description = Description;
Overlay = overlay;
}
}
public cMenuDataBase()
{
}
public cMenuDataBase(cFasdBaseConfigMenuItem menuItem)
{
MenuText = menuItem.Names.GetValue(Default: null);
MenuIcon = new MenuIconInfo(IconDataConverter.Convert(menuItem.Icon));
MenuSections = menuItem.Sections;
if (!string.IsNullOrEmpty(menuItem.Section))
MenuSections.Add(menuItem.Section);
MenuSections = MenuSections.Distinct().ToList();
}
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, Name = quickTip.Name };
}
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; } = new List<cMenuDataBase>();
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 private MenuIconInfo GetTicketIcon(Dictionary<string, string> infos)
{
bool isInactive = false;
if (infos.TryGetValue("StatusId", out var ticketStatusId))
{
if (Enum.TryParse(ticketStatusId, true, out enumTicketStatus ticketStatus))
{
switch (ticketStatus)
{
case enumTicketStatus.Closed:
isInactive = true;
break;
default:
break;
}
}
}
string description = null;
var overlay = isInactive ? (IconData?)new IconData(enumInternIcons.misc_disabledOverlay) : null;
if (isInactive)
{
}
if (infos.TryGetValue("TicketType", out var ticketType))
{
if (Enum.TryParse(ticketType, true, out enumTicketType parsedTicketType))
{
switch (parsedTicketType)
{
case enumTicketType.Incident:
if (isInactive)
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Incident.Closed");
else
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Incident.Active");
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_bug_report), description, isInactive, overlay);
case enumTicketType.ServiceRequest:
if (isInactive)
description = cMultiLanguageSupport.GetItem("Searchbar.Item.ServiceRequest.Closed");
else
description = cMultiLanguageSupport.GetItem("Searchbar.Item.ServiceRequest.Active");
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_room_service), description, isInactive, overlay);
case enumTicketType.UnclassifiedTicket:
if (isInactive)
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Unclassified.Closed");
else
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Unclassified.Active");
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_confirmation_number), description, isInactive, overlay);
default:
break;
}
}
}
if (isInactive)
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Ticket.Closed");
else
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Ticket.Active");
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_mail_outline), description, isInactive, overlay);
}
static private MenuIconInfo GetVirtualSessionIcon(Dictionary<string, string> infos)
{
if (infos.TryGetValue("Status", out string status))
{
if (status == nameof(enumCitrixSessionStatus.Active))
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_cloud_queue));
}
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_cloud_off));
}
static public MenuIconInfo GetMenuIcon(enumF4sdSearchResultClass searchResultClass, Dictionary<string, string> infos)
{
switch (searchResultClass)
{
case enumF4sdSearchResultClass.Computer:
return new MenuIconInfo(new IconData(enumInternIcons.misc_computer));
case enumF4sdSearchResultClass.User:
return new MenuIconInfo(new IconData(enumInternIcons.misc_user));
case enumF4sdSearchResultClass.Phone:
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_phone));
case enumF4sdSearchResultClass.Ticket:
return GetTicketIcon(infos);
case enumF4sdSearchResultClass.MobileDevice:
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_smartphone));
case enumF4sdSearchResultClass.VirtualSession:
return GetVirtualSessionIcon(infos);
default:
return new MenuIconInfo(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

@@ -49,7 +49,7 @@ namespace FasdDesktopUi.Basics.Models
try
{
cUtility.RawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
cUtility.RawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
var outputTable = dataProvider.HealthCardDataHelper.HealthCardRawData.GetTableByName(valueAdress.ValueTable, true);

View File

@@ -1,6 +1,7 @@
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Services.Models;
using FasdDesktopUi.Basics.UiActions;
using System.Linq;
using static C4IT.FASD.Base.cF4SDHealthCardRawData;
namespace FasdDesktopUi.Basics.Models
@@ -17,5 +18,17 @@ namespace FasdDesktopUi.Basics.Models
public cUiActionBase UiActionTitle { get; set; } = null;
public cUiActionBase UiActionValue { get; set; } = null;
public cHealthCardDetailsTable ValuedDetails { get; set; } = null;
public cWidgetValueModel() { }
public cWidgetValueModel(CockpitValueDisplayData displayData, enumHighlightColor highlightColor, cUiActionBase titleUiAction)
{
Title = displayData?.Title;
Value = displayData?.Values?.FirstOrDefault() ?? (displayData.IsLoading ? "..." : null);
HighlightIn = highlightColor;
IsLoading = displayData?.IsLoading ?? true;
UiActionTitle = titleUiAction;
UiActionValue = displayData?.UiActions?.FirstOrDefault();
}
}
}

View File

@@ -286,18 +286,20 @@ namespace FasdDesktopUi.Basics
public bool isSeen { get; set; } = false;
protected DateTime LastRefresh = DateTime.MinValue;
public IRelationService RelationService { get; private set; }
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)
public cSearchHistoryEntryBase(string DisplayText, List<cFasdApiSearchResultEntry> selectedSearchResult, List<cF4sdApiSearchResultRelation> relations, ISearchUiProvider SearchUiProvider, IRelationService relationService)
{
this.DisplayText = DisplayText;
this.isSeen = isSeen;
this.SelectedSearchResult = selectedSearchResult;
this.Relations = relations;
this.SearchUiProvider = SearchUiProvider;
RelationService = relationService;
LastRefresh = DateTime.UtcNow;
}
@@ -313,7 +315,7 @@ namespace FasdDesktopUi.Basics
{
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)
public cSearchHistorySearchResultEntry(string DisplayText, string HeaderText, List<cFasdApiSearchResultEntry> selectedSearchResult, List<cF4sdApiSearchResultRelation> relations, ISearchUiProvider SearchUiProvider, IRelationService relationService) : base(DisplayText, selectedSearchResult, relations, SearchUiProvider, relationService)
{
this.HeaderText = HeaderText;
LastRefresh = DateTime.UtcNow;
@@ -337,7 +339,7 @@ namespace FasdDesktopUi.Basics
{
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)
public cSearchHistoryRelationEntry(string DisplayText, List<cFasdApiSearchResultEntry> selectedSearchResult, List<cF4sdApiSearchResultRelation> relations, cF4sdApiSearchResultRelation selectedRealtion, ISearchUiProvider SearchUiProvider, IRelationService relationService) : base(DisplayText, selectedSearchResult, relations, SearchUiProvider, relationService)
{
SelectedRelation = selectedRealtion;
}

View File

@@ -0,0 +1,15 @@
using C4IT.FASD.Base;
using FasdDesktopUi.Basics.UiActions;
using System.Collections.Generic;
namespace FasdDesktopUi.Basics.Services.Models
{
public class CockpitValueDisplayData
{
public string Title { get; set; }
public IList<string> Values { get; set; }
public IList<enumHealthCardStateLevel> Levels { get; set; }
public bool IsLoading { get; set; }
public IList<cUiActionBase> UiActions { get; set; }
}
}

View File

@@ -19,20 +19,31 @@ namespace FasdDesktopUi.Basics.Services.ProtocollService
public static QuickActionProtocollEntry GetQuickActionProtocollEntry(cFasdQuickAction quickActionDefinition, cQuickActionCopyData quickActionCopyData)
{
string ascii = GetAscii(quickActionDefinition, quickActionCopyData);
string html = GetHtml(quickActionDefinition, quickActionCopyData);
string currentLanguage = cMultiLanguageSupport.CurrentLanguage;
return new QuickActionProtocollEntry(ascii, html)
try
{
Id = quickActionDefinition.Id,
Name = quickActionDefinition.Name,
ExecutionTypeId = (int)quickActionDefinition.ExecutionType,
WasRunningOnAffectedDevice = quickActionCopyData.WasRunningOnAffectedDevice,
AffectedDeviceName = quickActionCopyData.AffectedDeviceName,
ResultCode = (int?)quickActionCopyData.QuickActionOutput?.ResultCode,
ErrorMessage = quickActionCopyData.QuickActionOutput?.ErrorDescription,
MeasureValues = GetQuickActionHtmlValueComparison(quickActionCopyData.MeasureValues)
};
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage ?? currentLanguage;
string ascii = GetAscii(quickActionDefinition, quickActionCopyData);
string html = GetHtml(quickActionDefinition, quickActionCopyData);
return new QuickActionProtocollEntry(ascii, html)
{
Id = quickActionDefinition.Id,
Name = quickActionDefinition.Name,
ExecutionTypeId = (int)quickActionDefinition.ExecutionType,
WasRunningOnAffectedDevice = quickActionCopyData.WasRunningOnAffectedDevice,
AffectedDeviceName = quickActionCopyData.AffectedDeviceName,
ResultCode = (int?)quickActionCopyData.QuickActionOutput?.ResultCode,
ErrorMessage = quickActionCopyData.QuickActionOutput?.ErrorDescription,
MeasureValues = GetQuickActionHtmlValueComparison(quickActionCopyData.MeasureValues)
};
}
finally
{
cMultiLanguageSupport.CurrentLanguage = currentLanguage;
}
}
internal static cQuickActionCopyData GetCopyData(cFasdQuickAction quickActionDefinition, cSupportCaseDataProvider dataProvider, bool wasRunningOnAffectedDevice, cQuickActionOutput quickActionOutput, List<cQuickActionMeasureValue> measureValues)
@@ -93,7 +104,7 @@ namespace FasdDesktopUi.Basics.Services.ProtocollService
{
string ascii = string.Empty;
ascii += GetQuickActionAsciiDescription(quickActionDefinition,copyData.Name, copyData.AffectedDeviceName, copyData.WasRunningOnAffectedDevice, copyData.ExecutionTime, copyData.QuickActionOutput?.ResultCode);
ascii += GetQuickActionAsciiDescription(quickActionDefinition, copyData.Name, copyData.AffectedDeviceName, copyData.WasRunningOnAffectedDevice, copyData.ExecutionTime, copyData.QuickActionOutput?.ResultCode);
ascii += GetQuickActionAsciiError(copyData.QuickActionOutput?.ErrorDescription);
ascii += GetQuickActionAsciiOutput(quickActionDefinition, copyData.QuickActionOutput);
ascii += GetQuickActionAsciiValueComparisonString(copyData.MeasureValues);
@@ -101,7 +112,7 @@ namespace FasdDesktopUi.Basics.Services.ProtocollService
return ascii;
}
private static string GetQuickActionAsciiDescription(cFasdQuickAction quickActionDefinition,string quickActionName, string deviceName, bool wasRunningOnAffectedDevice, DateTime executionTime, enumQuickActionSuccess? quickActionStatus)
private static string GetQuickActionAsciiDescription(cFasdQuickAction quickActionDefinition, string quickActionName, string deviceName, bool wasRunningOnAffectedDevice, DateTime executionTime, enumQuickActionSuccess? quickActionStatus)
{
string asciiDescription = string.Empty;
try
@@ -125,7 +136,7 @@ namespace FasdDesktopUi.Basics.Services.ProtocollService
rawDescription = cMultiLanguageSupport.GetItem("QuickAction.RemoteSession.Copy.Description");
}
asciiDescription = string.Format(rawDescription, quickActionName, deviceName, executionTime.ToString("g", new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage)), quickActionStatusString);
}
catch (Exception E)
@@ -259,7 +270,7 @@ namespace FasdDesktopUi.Basics.Services.ProtocollService
output += AsciiSeperator + cMultiLanguageSupport.GetItem("QuickAction.Copy.Measure");
cUtility.RawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
cUtility.RawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
foreach (var measureValue in measureValues)
@@ -299,7 +310,7 @@ namespace FasdDesktopUi.Basics.Services.ProtocollService
try
{
output += GetQuickActionHtmlDescription(quickActionDefinition,copyData.Name, copyData.AffectedDeviceName, copyData.WasRunningOnAffectedDevice, copyData.ExecutionTime, copyData.QuickActionOutput?.ResultCode);
output += GetQuickActionHtmlDescription(quickActionDefinition, copyData.Name, copyData.AffectedDeviceName, copyData.WasRunningOnAffectedDevice, copyData.ExecutionTime, copyData.QuickActionOutput?.ResultCode);
output += GetQuickActionHtmlError(copyData.QuickActionOutput?.ErrorDescription);
output += GetQuickActionHtmlOutput(quickActionDefinition, copyData.QuickActionOutput);
output += GetQuickActionHtmlValueComparison(copyData.MeasureValues);
@@ -331,7 +342,7 @@ namespace FasdDesktopUi.Basics.Services.ProtocollService
}
var rawDescription = wasRunningOnAffectedDevice ? cMultiLanguageSupport.GetItem("QuickAction.Remote.Copy.Description.Html") : cMultiLanguageSupport.GetItem("QuickAction.Local.Copy.Description.Html");
if(quickActionDefinition.Section == enumDataHistoryOrigin.Citrix.ToString())
if (quickActionDefinition.Section == enumDataHistoryOrigin.Citrix.ToString())
{
rawDescription = cMultiLanguageSupport.GetItem("QuickAction.RemoteSession.Copy.Description.Html");
@@ -479,7 +490,7 @@ namespace FasdDesktopUi.Basics.Services.ProtocollService
output += "<p>" + cMultiLanguageSupport.GetItem("QuickAction.Copy.Measure.Html") + "</p>";
cUtility.RawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
cUtility.RawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
foreach (var measureValue in measureValues)

View File

@@ -9,8 +9,10 @@ namespace FasdDesktopUi.Basics.Services.RelationService
public interface IRelationService
{
event EventHandler<StagedSearchResultRelationsEventArgs> RelationsFound;
event EventHandler RelationsReset;
IEnumerable<cF4sdApiSearchResultRelation> GetLoadedRelations();
void Reset();
IReadOnlyList<cF4sdApiSearchResultRelation> GetLoadedRelations();
Task<cF4sdStagedSearchResultRelationTaskId> LoadRelationsAsync(IEnumerable<cFasdApiSearchResultEntry> relatedTo, CancellationToken token = default);
IRelationService Clone();
}

View File

@@ -14,8 +14,17 @@ namespace FasdDesktopUi.Basics.Services.RelationService
{
internal class RelationService : IRelationService
{
private readonly object _relationsLock = new object();
private IEnumerable<cF4sdApiSearchResultRelation> _relations = new List<cF4sdApiSearchResultRelation>();
public void Reset()
{
lock (_relationsLock)
_relations = _relations.Where(r => r.Type == enumF4sdSearchResultClass.User).ToList();
RelationsReset?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Asynchronously loads relations for the specified search results.
/// </summary>
@@ -27,24 +36,14 @@ namespace FasdDesktopUi.Basics.Services.RelationService
{
try
{
_relations = relatedTo?.Select(searchResult => new cF4sdApiSearchResultRelation(searchResult)).ToList() ?? new List<cF4sdApiSearchResultRelation>();
lock (_relationsLock)
_relations = relatedTo?.Select(searchResult => new cF4sdApiSearchResultRelation(searchResult)).ToList() ?? 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);
if (gatherRelationTask is null)
return null;
_relations = _relations.Union(stagedRelations.Relations);
RelationsFound?.Invoke(this, new StagedSearchResultRelationsEventArgs() { RelatedTo = relatedTo, StagedResultRelations = stagedRelations, RelationService = this });
if (stagedRelations?.IsComplete ?? false)
break;
}
});
_ = Task.Run(async () => await GatherRelationsAsync(gatherRelationTask.Id, relatedTo, token));
return gatherRelationTask;
}
@@ -56,15 +55,56 @@ namespace FasdDesktopUi.Basics.Services.RelationService
return null;
}
public IEnumerable<cF4sdApiSearchResultRelation> GetLoadedRelations() => _relations;
private async Task GatherRelationsAsync(Guid gatherTaskId, IEnumerable<cFasdApiSearchResultEntry> relatedTo, CancellationToken token = default)
{
try
{
const int maxRetryCount = 10;
for (int i = 0; i < maxRetryCount; i++)
{
if (token.IsCancellationRequested)
{
await cFasdCockpitCommunicationBase.Instance.StopGatheringRelations(gatherTaskId, CancellationToken.None);
return;
}
cF4sdStagedSearchResultRelations stagedRelations = await cFasdCockpitCommunicationBase.Instance.GetStagedRelations(gatherTaskId, token);
if (stagedRelations is null)
continue;
stagedRelations.MergeAsRelationInfosWith(relatedTo);
lock (_relationsLock)
_relations = _relations.Union(stagedRelations.Relations).ToList();
RelationsFound?.Invoke(this, new StagedSearchResultRelationsEventArgs() { RelatedTo = relatedTo, StagedResultRelations = stagedRelations, RelationService = this });
if (stagedRelations?.IsComplete ?? false)
break;
}
}
catch (Exception ex)
{
LogException(ex);
}
}
public IReadOnlyList<cF4sdApiSearchResultRelation> GetLoadedRelations()
{
lock (_relationsLock)
return _relations.ToList();
}
public IRelationService Clone()
{
RelationService copy = (RelationService)MemberwiseClone();
copy._relations = _relations.Select(r => r).ToList();
RelationService copy = new RelationService();
lock (_relationsLock)
copy._relations = _relations.ToList();
return copy;
}
public event EventHandler RelationsReset;
public event EventHandler<StagedSearchResultRelationsEventArgs> RelationsFound;
}
}

View File

@@ -0,0 +1,136 @@
using C4IT.FASD.Cockpit.Communication;
using F4SD.Gamification.Services;
using FasdCockpitBase.Models.RemoteDesktopConnection;
using FasdCockpitCommunication.RemoteDesktopCommunication;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.Services.RemoteDesktop
{
internal static class AgentRemoteDesktopService
{
private static readonly Dictionary<Guid, Process> _viewerProcesses = new Dictionary<Guid, Process>();
internal static async Task<RemoteDesktopConnectionStatusResult> StartRemoteDesktopConnectionAsync(AgentRemoteClientInfo clientInfo, bool isElevated, CancellationToken token = default)
{
const int maxRetryCount = 20;
TimeSpan baseDelay = TimeSpan.FromSeconds(0.5);
AgentRemoteDesktopConnecitonDetails connectionDetails = await cFasdCockpitCommunicationBase.Instance.RemoteDesktopManager.InitiateConnection<AgentRemoteDesktopConnecitonDetails>(clientInfo, isElevated, token);
RemoteConnetionStatusChanged?.Invoke(null, RemoteDesktopConnectionStatus.Initiated);
if (token.IsCancellationRequested)
{
RemoteConnetionStatusChanged?.Invoke(null, RemoteDesktopConnectionStatus.Canceled);
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Canceled);
}
if (connectionDetails is null)
{
LogEntry("Could not initiate remote connection.", C4IT.Logging.LogLevels.Warning);
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Unknown);
}
if (connectionDetails.Errors != null && connectionDetails.Errors.Count > 0)
{
RemoteConnetionStatusChanged?.Invoke(null, RemoteDesktopConnectionStatus.Error);
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Error) { Errors = connectionDetails.Errors.Select(e => e.Message).ToArray() };
}
RemoteDesktopConnectionStatusResult connectionStatus = null;
for (int i = 0; i < maxRetryCount; i++)
{
try
{
connectionStatus = await cFasdCockpitCommunicationBase.Instance.RemoteDesktopManager.GetConnectionStatus(connectionDetails.ConnectionId, token);
LogEntry($"Update {i} RemoteDesktop connection status: {connectionStatus}", C4IT.Logging.LogLevels.Debug);
if (token.IsCancellationRequested || IsRemoteConnectionEstablished(connectionStatus.Status))
break;
await Task.Delay(TimeSpan.FromTicks(baseDelay.Ticks * i));
}
catch (Exception ex)
{
LogException(ex);
}
}
if (token.IsCancellationRequested)
{
RemoteConnetionStatusChanged?.Invoke(null, RemoteDesktopConnectionStatus.Canceled);
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Canceled);
}
RemoteConnetionStatusChanged?.Invoke(null, connectionStatus.Status);
if (connectionStatus.Status != RemoteDesktopConnectionStatus.Accepted)
{
LogEntry($"Could not connect to remote desktop. Status: {connectionStatus}", C4IT.Logging.LogLevels.Warning);
return new RemoteDesktopConnectionStatusResult(connectionStatus.Status);
}
StartViewer(connectionDetails);
GamificationService.TrackAction(F4SD.Gamification.CockpitAction.StartRemoteConnection);
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Connected);
}
private static bool IsRemoteConnectionEstablished(RemoteDesktopConnectionStatus status)
{
switch (status)
{
case RemoteDesktopConnectionStatus.Accepted:
case RemoteDesktopConnectionStatus.Connected:
case RemoteDesktopConnectionStatus.Finished:
case RemoteDesktopConnectionStatus.Canceled:
return true;
case RemoteDesktopConnectionStatus.Unknown:
case RemoteDesktopConnectionStatus.Initiated:
default:
return false;
}
}
private static void StartViewer(AgentRemoteDesktopConnecitonDetails connectionDetails)
{
try
{
ProcessStartInfo info = new ProcessStartInfo(GetViewerPath())
{
Arguments = $"-connectionId {connectionDetails.ConnectionId} -phoenixServiceUrl {connectionDetails.PhoenixServiceUrl} -secret {connectionDetails.Secret}"
};
Process process = Process.Start(info);
_viewerProcesses.Add(connectionDetails.ConnectionId, process);
RemoteConnetionStatusChanged?.Invoke(null, RemoteDesktopConnectionStatus.Connected);
}
catch (Exception ex)
{
LogException(ex);
}
}
internal static async Task StopRemoteDesktopConnection(Guid connectionId, CancellationToken token = default)
{
await cFasdCockpitCommunicationBase.Instance.RemoteDesktopManager.StopConnection(connectionId, token);
if (_viewerProcesses.TryGetValue(connectionId, out var process))
process.Close();
}
internal static string GetViewerPath()
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Phoenix\Phoenix.Viewer.exe").ToString();
}
internal static EventHandler<RemoteDesktopConnectionStatus> RemoteConnetionStatusChanged;
}
}

View File

@@ -0,0 +1,48 @@
using C4IT.FASD.Base;
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using System.Collections.Generic;
namespace FasdDesktopUi.Basics.Services.SupportCase.Controllers
{
internal static class MenuDataFactory
{
internal static cMenuDataBase GetByName(string name, cNamedParameterList namedParameterEntries, IEnumerable<enumFasdInformationClass> availableInformationClasses)
{
if (!cF4SDCockpitXmlConfig.Instance.MenuItems.TryGetValue(name, out var menuDataDefinition))
return null;
return Create(menuDataDefinition, namedParameterEntries, availableInformationClasses);
}
internal static cMenuDataBase Create(cFasdBaseConfigMenuItem definition, cNamedParameterList namedParameterEntries, IEnumerable<enumFasdInformationClass> availableInformationClasses)
{
cMenuDataBase menuData;
switch (definition)
{
case cFasdQuickAction quickActionDefinition:
menuData = new cMenuDataBase(quickActionDefinition);
break;
case cCopyTemplate copyTemplate:
menuData = new cMenuDataBase(copyTemplate);
break;
case cFasdMenuSection sectionDefinition:
menuData = new cMenuDataContainer(sectionDefinition);
break;
case cFasdQuickTip quickTip:
menuData = new cMenuDataBase(quickTip);
break;
default:
menuData = new cMenuDataBase(definition);
break;
}
enumActionDisplayType displayType = ActionDisplayTypeInspector.GetDisplayType(definition, namedParameterEntries, availableInformationClasses);
menuData.SetUiActionDisplayType(displayType);
return menuData;
}
}
}

View File

@@ -1,7 +1,12 @@
using C4IT.FASD.Base;
using C4IT.FASD.Cockpit.Communication;
using FasdCockpitCommunication.RemoteDesktopCommunication;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.Models;
using FasdDesktopUi.Basics.Services.SupportCase.Processors;
using FasdDesktopUi.Basics.UiActions;
using FasdDesktopUi.Pages.DetailsPage.Models;
using System;
using System.Collections.Generic;
@@ -12,18 +17,18 @@ using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.Services.SupportCase.Controllers
{
/// <summary>
/// Used to manage the <see cref="ISupportCase"/> for the UI via the <see cref="SupportCaseProcessor"/>
/// Used to manage the <see cref="ISupportCase"/> for the UI via the <see cref="ISupportCaseProcessor"/>
/// </summary>
public class SupportCaseController
{
private SupportCaseProcessor _supportCaseProcessor;
private ISupportCaseProcessor _supportCaseProcessor;
private cF4sdApiSearchResultRelation _focusedRelation;
private readonly Dictionary<enumFasdInformationClass, cF4sdApiSearchResultRelation> _selectedRelations = new Dictionary<enumFasdInformationClass, cF4sdApiSearchResultRelation>();
private cHealthCard _selectedHealthcard = null;
private bool _hasDirectionConnection = false;
public cSupportCaseDataProvider SupportCaseDataProviderArtifact { get => _supportCaseProcessor?.SupportCaseDataProviderArtifact; }
internal void SetSupportCaseProcessor(SupportCaseProcessor supportCaseProcessor, IEnumerable<cF4sdIdentityEntry> preselectedIdentities)
internal void SetSupportCaseProcessor(ISupportCaseProcessor supportCaseProcessor, IEnumerable<cF4sdIdentityEntry> preselectedIdentities)
{
IEnumerable<cF4sdApiSearchResultRelation> preselectedRelations = GetPreselectedRelations(supportCaseProcessor.GetCaseRelations(), preselectedIdentities);
@@ -88,6 +93,9 @@ namespace FasdDesktopUi.Basics.Services.SupportCase.Controllers
{
CaseDataChanged?.Invoke(this, e);
if (e.DataTables.Any(t => !t.Name.StartsWith("Computation_")))
_supportCaseProcessor.ProcessComputations(e.Relation, _supportCaseProcessor.GetHealthcardFor(e.Relation).Prerequisites.Computations.Values);
_ = Task.Run(async () =>
{
await UpdateStatusOfSelectedRelations();
@@ -220,7 +228,7 @@ namespace FasdDesktopUi.Basics.Services.SupportCase.Controllers
relationEntry.Value.Infos[StatusString] = statusValue;
}
IEnumerable<cHeadingDataModel> newHeadingData = SupportCaseHeadingController.GetHeadingData(_selectedRelations);
IEnumerable<cHeadingDataModel> newHeadingData = GetHeadingData();
HeadingDataChanged?.Invoke(this, new HeadingDataEventArgs(newHeadingData));
}
catch (Exception ex)
@@ -234,18 +242,209 @@ namespace FasdDesktopUi.Basics.Services.SupportCase.Controllers
SupportCaseDataProviderArtifact.HealthCardDataHelper.LoadingHelper.LastDataRequest = DateTime.Now;
await _supportCaseProcessor.UpdateLatestCaseDataFor(_focusedRelation);
}
public cCopyTemplate GetCopyTemplate()
{
string defaultCopyTemplate = _selectedHealthcard?.DefaultCopyTemplate
?? cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate.Name
?? string.Empty;
public List<List<cWidgetValueModel>> GetWidgetData()
=> _supportCaseProcessor.GetWidgetData(_focusedRelation);
Dictionary<string, cCopyTemplate> copyTemplates = cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates?.CopyTemplates;
if (copyTemplates?.TryGetValue(defaultCopyTemplate, out cCopyTemplate _defaultCopyTemplate) ?? false)
return _defaultCopyTemplate;
else
return null;
}
public List<List<cWidgetValueModel>> GetWidgetsData()
{
try
{
List<List<cWidgetValueModel>> widgetsData = new List<List<cWidgetValueModel>>();
cHealthCard currentHealthCard = _supportCaseProcessor.GetHealthcardFor(_focusedRelation);
IEnumerable<cHealthCardStateCategory> widgetsDefinition = currentHealthCard.CategoriesStatic.StateCategories;
foreach (var widgetDefinition in widgetsDefinition)
{
List<cWidgetValueModel> widgetData = new List<cWidgetValueModel>();
foreach (var widgetValueDefinition in widgetDefinition.States)
{
CockpitValueDisplayData displayData = _supportCaseProcessor.GetCockpitValueDisplayData(widgetValueDefinition, _focusedRelation, true);
cUiActionBase uiAction = _supportCaseProcessor.GetUiAction(widgetValueDefinition);
var widgetValue = new cWidgetValueModel(displayData, GetHighlightColor(displayData?.Levels?.FirstOrDefault() ?? enumHealthCardStateLevel.None), uiAction);
if (widgetValue?.UiActionValue != null && ShouldHideUiActionValue(widgetValue.Value))
widgetValue.UiActionValue.DisplayType = enumActionDisplayType.hidden;
widgetData.Add(widgetValue);
}
widgetsData.Add(widgetData);
}
return widgetsData;
}
catch (Exception ex)
{
LogException(ex);
return null;
}
bool ShouldHideUiActionValue(string widgetValue)
=> string.IsNullOrWhiteSpace(widgetValue) || widgetValue == "0";
}
public cDetailsPageDataHistoryDataModel GetHistoryData()
=> _supportCaseProcessor.GetHistoryData(_focusedRelation);
=> ((SupportCaseProcessor)_supportCaseProcessor).GetHistoryData(_focusedRelation);
public List<cContainerCollectionData> GetContainerData()
=> _supportCaseProcessor.GetContainerData(_focusedRelation);
=> ((SupportCaseProcessor)_supportCaseProcessor).GetContainerData(_focusedRelation);
public List<cMenuDataBase> GetMenuBarData()
=> _supportCaseProcessor.GetMenuBarData(_focusedRelation);
public IEnumerable<cMenuDataBase> GetMenuData()
{
var menuBarDatas = cF4SDCockpitXmlConfig.Instance.MenuItems.ToDictionary(config => config.Key, config => (Config: config.Value, MenuValue: MenuDataFactory.Create(config.Value, _supportCaseProcessor.SupportCaseDataProviderArtifact.NamedParameterEntries, _selectedRelations.Values.Select(r => cF4sdIdentityEntry.GetFromSearchResult(r.Type)).ToList())));
try
{
List<string> menuBarDatasAddedToSection = new List<string>();
foreach (var menuBarData in menuBarDatas.Values)
{
bool isPinned = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.QuickActionsPinned.Contains(menuBarData.Config.Name);
menuBarData.MenuValue.IconPositionIndex = isPinned ? cF4SDCockpitXmlConfig.Instance.HealthCardConfig.QuickActionsPinned.IndexOf(menuBarData.Config.Name) : -1;
// Same Logic in GetFilteredMenuData()
bool hasBeenAddedToSection = TryAddMenuDataToSection(ref menuBarDatas, menuBarData.Config.Section, menuBarData.MenuValue);
foreach (var section in menuBarData.Config.Sections)
{
// todo add test for adding to multiple sections
hasBeenAddedToSection = TryAddMenuDataToSection(ref menuBarDatas, section, menuBarData.MenuValue) || hasBeenAddedToSection; // order is relevent, because data has to be added to section
}
if (hasBeenAddedToSection)
menuBarDatasAddedToSection.Add(menuBarData.Config.Name);
}
foreach (var menuBarData in menuBarDatasAddedToSection)
{
if (cF4SDCockpitXmlConfig.Instance.HealthCardConfig.QuickActionsPinned.Contains(menuBarData))
continue;
menuBarDatas.Remove(menuBarData);
}
return menuBarDatas.Values.Select(data => data.MenuValue);
}
catch (Exception ex)
{
LogException(ex);
return new List<cMenuDataBase>();
}
}
public IEnumerable<cMenuDataBase> GetFilteredMenuData(MenuDataFilter filterQuery)
{
Dictionary<string, (cFasdBaseConfigMenuItem Config, cMenuDataBase MenuValue)> menuBarDatas = cF4SDCockpitXmlConfig.Instance.MenuItems.ToDictionary(config => config.Key, config => (Config: config.Value, MenuValue: MenuDataFactory.Create(config.Value, _supportCaseProcessor.SupportCaseDataProviderArtifact.NamedParameterEntries, _selectedRelations.Values.Select(r => cF4sdIdentityEntry.GetFromSearchResult(r.Type)).ToList())));
try
{
foreach (var menuBarData in menuBarDatas.Values)
{
// Same Logic in GetMenuData()
bool hasBeenAddedToSection = TryAddMenuDataToSection(ref menuBarDatas, menuBarData.Config.Section, menuBarData.MenuValue);
foreach (var section in menuBarData.Config.Sections)
{
// todo add test for adding to multiple sections
hasBeenAddedToSection = TryAddMenuDataToSection(ref menuBarDatas, section, menuBarData.MenuValue) || hasBeenAddedToSection; // order is relevent, because data has to be added to section
}
}
return menuBarDatas.Values.Select(data => data.MenuValue)
.Where(md => md.MenuText.ToLower().Contains(filterQuery?.SearchString?.ToLower()));
}
catch (Exception ex)
{
LogException(ex);
return new List<cMenuDataBase>();
}
}
private bool TryAddMenuDataToSection(ref Dictionary<string, (cFasdBaseConfigMenuItem Config, cMenuDataBase MenuValue)> menuBarDatas, string section, cMenuDataBase menuData)
{
if (string.IsNullOrEmpty(section))
return false;
if (!menuBarDatas.TryGetValue(section, out var sectionMenuBar))
return false;
if (!(sectionMenuBar.MenuValue is cMenuDataContainer containerData))
return false;
if (containerData.UiAction is cSubMenuAction subMenuAction)
{
if (!subMenuAction.SubMenuData.Any(item => item.MenuText == menuData.MenuText)) // todo SubMenuData maybe better as Dictionary<Guid, cMenuDataBase>
subMenuAction.SubMenuData.Add(menuData);
if (!containerData.SubMenuData.Any(item => item.MenuText == menuData.MenuText))
containerData.SubMenuData.Add(menuData);
}
return true;
}
internal IEnumerable<cHeadingDataModel> GetHeadingData()
=> SupportCaseHeadingController.GetHeadingData(_selectedRelations);
private static enumHighlightColor GetHighlightColor(enumHealthCardStateLevel level)
{
switch (level)
{
case enumHealthCardStateLevel.None:
return enumHighlightColor.none;
case enumHealthCardStateLevel.Ok:
return enumHighlightColor.green;
case enumHealthCardStateLevel.Warning:
return enumHighlightColor.orange;
case enumHealthCardStateLevel.Error:
return enumHighlightColor.red;
case enumHealthCardStateLevel.Info:
return enumHighlightColor.blue;
default:
return enumHighlightColor.none;
}
}
internal IEnumerable<cF4sdApiSearchResultRelation> GetRelationsOf(enumFasdInformationClass informationClass)
{
return _supportCaseProcessor.GetCaseRelations().FirstOrDefault(r => r.Key == informationClass);
}
internal AgentRemoteClientInfo GetAgentClientInfo()
{
if (_focusedRelation.Type != enumF4sdSearchResultClass.Computer)
return null;
int deviceId = 0;
int userId = 0;
bool hasAllRequiredNamedParameters =
_supportCaseProcessor.TryGetNamedParameterValue(_focusedRelation, SupportCaseProcessor.AgentOrganisationCodeNamedParameterName, out int organisationId)
&& _supportCaseProcessor.TryGetNamedParameterValue(_focusedRelation, SupportCaseProcessor.AgentUserIdNamedParameterName, out userId)
&& _supportCaseProcessor.TryGetNamedParameterValue(_focusedRelation, SupportCaseProcessor.AgentDeviceIdNamedParameterName, out deviceId);
if (!hasAllRequiredNamedParameters)
return null;
return new AgentRemoteClientInfo()
{
DeviceCode = deviceId,
AccountCode = userId,
OrganisationCode = organisationId
};
}
/// <summary>
/// Raised when the currently for a support case relevant and shown relations have been updated.
@@ -264,4 +463,15 @@ namespace FasdDesktopUi.Basics.Services.SupportCase.Controllers
public event EventHandler<HeadingDataEventArgs> HeadingDataChanged;
}
public class MenuDataFilter
{
public string SearchString { get; set; }
public MenuDataFilter(string searchString = null)
{
SearchString = searchString;
}
}
}

View File

@@ -68,6 +68,7 @@ namespace FasdDesktopUi.Basics.Services.SupportCase.Controllers
{
case enumF4sdSearchResultClass.Computer:
case enumF4sdSearchResultClass.User:
case enumF4sdSearchResultClass.Phone:
isOnline = string.Equals(statusValue, "Online", StringComparison.InvariantCultureIgnoreCase);
break;
case enumF4sdSearchResultClass.Ticket:

View File

@@ -14,7 +14,7 @@ namespace FasdDesktopUi.Basics.Services.SupportCase
void AddCaseRelations(ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> relations);
ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> GetCaseRelations();
Task LoadSupportCaseDataAsync(cF4sdApiSearchResultRelation relation, IEnumerable<string> tablesToLoad);
IEnumerable<object> GetSupportCaseHealthcardData(cF4sdApiSearchResultRelation relation, cValueAddress valueAddress);
IList<object> GetSupportCaseHealthcardData(cF4sdApiSearchResultRelation relation, cValueAddress valueAddress, bool getStatic);
void UpdateSupportCaseDataCache(cF4sdApiSearchResultRelation relation, IEnumerable<cF4SDHealthCardRawData.cHealthCardTable> tables);
void InvalidateCaseDataCacheFor(cF4sdApiSearchResultRelation relation);
void InvalidateLatestCaseDataCacheFor(cF4sdApiSearchResultRelation relation, out ICollection<cF4SDHealthCardRawData.cHealthCardTable> invalidatedTables);

View File

@@ -0,0 +1,29 @@
using C4IT.FASD.Base;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Services.Models;
using FasdDesktopUi.Basics.UiActions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace FasdDesktopUi.Basics.Services.SupportCase.Processors
{
internal interface ISupportCaseProcessor
{
cSupportCaseDataProvider SupportCaseDataProviderArtifact { get; }
event EventHandler<RelationEventArgs> AvailableCaseRelationsAdded;
event EventHandler<SupportCaseDataEventArgs> CaseDataChanged;
void SetSupportCase(ISupportCase supportCase);
CockpitValueDisplayData GetCockpitValueDisplayData(cHealthCardStateBase displayValueDefinition, cF4sdApiSearchResultRelation relation, bool getStatic);
Task LoadSupportCaseDataAsync(cF4sdApiSearchResultRelation relation, IEnumerable<string> tablesToLoad);
void ProcessComputations(cF4sdApiSearchResultRelation relation, IEnumerable<cHealthCardComputationBase> computations);
Task UpdateLatestCaseDataFor(cF4sdApiSearchResultRelation relation);
ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> GetCaseRelations();
cHealthCard GetHealthcardFor(cF4sdApiSearchResultRelation relation);
cUiActionBase GetUiAction(cHealthCardStateBase stateDefinition);
bool TryGetNamedParameterValue<T>(cF4sdApiSearchResultRelation relation, string parameterName, out T value);
}
}

View File

@@ -0,0 +1,145 @@
using C4IT.F4SD.DisplayFormatting;
using C4IT.FASD.Base;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.Services.SupportCase.Processors
{
internal class SupportCaseDetailsValueProcessesor
{
/// <summary>
/// Transform a value to a <seealso cref="cF4SDHealthCardRawData.cHealthCardDetailsTable"/>
/// </summary>
/// <param name="rawValue">Raw value in form of CSV or JSON</param>
/// <param name="stateDetailsValued">Details definition the transformation is based on</param>
/// <returns></returns>
internal static cF4SDHealthCardRawData.cHealthCardDetailsTable GetDetailsTable(object rawValue, cHealthCardDetailsValued stateDetailsValued)
{
try
{
if (rawValue is null)
return null;
var stringValue = cUtility.RawValueFormatter.GetDisplayValue(rawValue, RawValueType.STRING);
if (stringValue is null)
return null;
List<object[]> tableValues = stateDetailsValued.Format == cHealthCardDetailsValued.ValuedFormat.json
? ParseJson(stringValue, stateDetailsValued)
: ParseCsv(stringValue, stateDetailsValued);
tableValues = tableValues ?? new List<object[]>();
var detailedValueTable = new cF4SDHealthCardRawData.cHealthCardDetailsTable()
{
Name = "Details-" + stateDetailsValued.ParentState.Name,
Columns = stateDetailsValued.Select(v => v.Names.GetValue()).ToList(),
Values = new Dictionary<int, List<object[]>>() { { 0, tableValues } }
};
return detailedValueTable;
}
catch (Exception ex)
{
LogException(ex);
}
return null;
}
private static List<object[]> ParseJson(string text, cHealthCardDetailsValued details)
{
try
{
var jObjects = JsonConvert.DeserializeObject<List<JObject>>(text);
if (jObjects == null || jObjects.Count == 0)
return new List<object[]>();
var values = new List<object[]>();
foreach (JObject jObject in jObjects)
{
var valueRow = new object[details.Count];
for (int i = 0; i < details.Count; i++)
valueRow[i] = null;
foreach (var jProp in jObject.Properties())
{
var name = jProp.Name;
var index = details.FindIndex(v => v.Column.Equals(name, StringComparison.InvariantCultureIgnoreCase));
if (index < 0)
continue;
var column = details[index];
if (jProp.Value is JValue jValue)
{
var value = jValue.Value;
valueRow[index] = cUtility.RawValueFormatter.GetDisplayValue(value, column.DisplayType);
}
}
values.Add(valueRow);
}
return values;
}
catch (Exception)
{
return new List<object[]>();
}
}
private static List<object[]> ParseCsv(string text, cHealthCardDetailsValued details)
{
var values = new List<object[]>();
var rows = text.Split(details.RowSeparator);
foreach (var row in rows)
{
if (string.IsNullOrWhiteSpace(row))
continue;
var entry = new List<object>();
if (details.ColSeparator == null)
{
entry.Add(row.Trim());
}
else
{
var columns = row.Split((char)details.ColSeparator);
foreach (var column in columns)
entry.Add(column?.Trim());
}
while (entry.Count < details.Count)
entry.Add(null);
values.Add(entry.ToArray());
}
return values;
}
/// <summary>
/// Get a display string based on StateDetails and its values
/// </summary>
internal static string GetDetailStringValue(cHealthCardDetailsBase details, cF4SDHealthCardRawData.cHealthCardDetailsTable detailTableValueTable)
{
if (detailTableValueTable?.Values is null || detailTableValueTable.Values.Count == 0)
return null;
var tableValues = detailTableValueTable.Values.First().Value;
if (detailTableValueTable.Columns.Count >= 1 && tableValues.Count == 1)
return cUtility.RawValueFormatter.GetDisplayValue(detailTableValueTable.Values.First().Value.First()?.First(), details.First().DisplayType);
else
return cUtility.RawValueFormatter.GetDisplayValue(detailTableValueTable.Values.First().Value.Count, RawValueType.STRING);
}
}
}

View File

@@ -0,0 +1,643 @@
using C4IT.FASD.Base;
using C4IT.FASD.Cockpit.Communication;
using C4IT.Logging;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.Models;
using FasdDesktopUi.Basics.Services.SupportCase.Controllers;
using FasdDesktopUi.Basics.UiActions;
using FasdDesktopUi.Pages.DetailsPage.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.Services.SupportCase.Processors
{
/// <summary>
/// Used for processing raw data of a <see cref="ISupportCase"/> for the UI in a certain way.
/// </summary>
internal class SupportCaseProcessor : ISupportCaseProcessor
{
internal const string AgentDeviceIdNamedParameterName = "F4SD_Agent_DeviceId";
internal const string AgentUserIdNamedParameterName = "F4SD_Agent_UserId";
internal const string AgentOrganisationCodeNamedParameterName = "F4SD_Agent_OrganisationId";
private ISupportCase _supportCase;
public cSupportCaseDataProvider SupportCaseDataProviderArtifact { get => _supportCase?.SupportCaseDataProviderArtifact; }
private readonly Dictionary<cF4sdApiSearchResultRelation, cDetailsPageData> _detailsPageDataCache = new Dictionary<cF4sdApiSearchResultRelation, cDetailsPageData>();
private readonly Dictionary<cF4sdApiSearchResultRelation, Dictionary<string, object>> _namedParameterCache = new Dictionary<cF4sdApiSearchResultRelation, Dictionary<string, object>>();
private readonly Dictionary<cF4sdApiSearchResultRelation, Dictionary<string, IList<object>>> _computationCache = new Dictionary<cF4sdApiSearchResultRelation, Dictionary<string, IList<object>>>();
public void SetSupportCase(ISupportCase supportCase)
{
if (_supportCase != null)
{
_supportCase.CaseRelationsAdded -= HandleSupportCaseRelationsAdded;
_supportCase.SupportCaseDataCacheHasChanged -= HandleSupportCaseDataCacheHasChanged;
}
_supportCase = supportCase;
_supportCase.CaseRelationsAdded += HandleSupportCaseRelationsAdded;
_supportCase.SupportCaseDataCacheHasChanged += HandleSupportCaseDataCacheHasChanged;
}
private void HandleSupportCaseRelationsAdded(object sender, RelationEventArgs e)
=> AvailableCaseRelationsAdded?.Invoke(this, e);
private async void HandleSupportCaseDataCacheHasChanged(object sender, SupportCaseDataEventArgs e)
{
bool isArtifactShowingCorrectHealthCard
= SupportCaseDataProviderArtifact.HealthCardDataHelper.SelectedHealthCard == GetHealthcardFor(e.Relation);
if (!isArtifactShowingCorrectHealthCard)
{
// todo this can probably be removed, as soon as the last dependency of the SupportCaseDataProviderArtifact is gone.
// till then the detailspageData gets overriden with the detailspageData of the new relation.
// However, the removal shouldn't be much of a problem, due to the fact the Artifact also stores the raw data
_detailsPageDataCache.Remove(e.Relation);
return;
}
await EnsureDetailsPageDataCachedAsync(e.Relation).ConfigureAwait(false);
UpdateNamedParameters(e.Relation, e.DataTables);
CaseDataChanged?.Invoke(this, e);
}
private async Task EnsureDetailsPageDataCachedAsync(cF4sdApiSearchResultRelation relation)
{
if (!_detailsPageDataCache.TryGetValue(relation, out var cachedData))
{
_detailsPageDataCache[relation] = await _supportCase.SupportCaseDataProviderArtifact.HealthCardDataHelper.DetailPage.GetDataAsync().ConfigureAwait(false);
return;
}
cDetailsPageData detailData = _supportCase.SupportCaseDataProviderArtifact.HealthCardDataHelper.DetailPage.GetDataWithoutHeading();
cachedData.WidgetData = detailData.WidgetData;
cachedData.DataHistoryList = detailData.DataHistoryList;
cachedData.MenuBarData = detailData.MenuBarData;
cachedData.DataContainerCollectionList = detailData.DataContainerCollectionList;
}
private void UpdateNamedParameters(cF4sdApiSearchResultRelation relation, IEnumerable<cF4SDHealthCardRawData.cHealthCardTable> dataTables)
{
try
{
if (!_namedParameterCache.ContainsKey(relation))
_namedParameterCache.Add(relation, new Dictionary<string, object>());
var healthcard = GetHealthcardFor(relation);
foreach (var namedParameter in cHealthCardPrerequisites.GetNamedParameters(healthcard).Values)
{
var table = dataTables.FirstOrDefault(t => t.Name == namedParameter.DatabaseInfo.ValueTable);
if (table is null)
continue;
if (!table.Columns.TryGetValue(namedParameter.DatabaseInfo.ValueColumn, out var column))
continue;
string value = cUtility.RawValueFormatter.GetDisplayValue(column.Values.FirstOrDefault(), namedParameter.Display);
_namedParameterCache[relation][namedParameter.ParameterName] = value;
}
AddDefaultNamedParameters();
}
catch (Exception ex)
{
LogException(ex);
}
void AddDefaultNamedParameters()
{
var table = dataTables.FirstOrDefault(t => t.Name == "agnt-computer");
if (table != null)
{
if (table.Columns.TryGetValue("id", out var agentDeviceIdColumn))
_namedParameterCache[relation][AgentDeviceIdNamedParameterName] = agentDeviceIdColumn.Values.FirstOrDefault();
}
table = dataTables.FirstOrDefault(t => t.Name == "agnt-user");
if (table != null)
{
if (table.Columns.TryGetValue("id", out var agentUserColumn))
_namedParameterCache[relation][AgentUserIdNamedParameterName] = agentUserColumn.Values.FirstOrDefault();
}
_namedParameterCache[relation][AgentOrganisationCodeNamedParameterName] = cCockpitConfiguration.Instance.agentApiConfiguration.OrganizationCode;
}
}
public async Task LoadSupportCaseDataAsync(cF4sdApiSearchResultRelation relation, IEnumerable<string> tablesToLoad)
{
_ = Task.Run(async () => await _supportCase.LoadSupportCaseDataAsync(relation, tablesToLoad.Where(t => !t.Contains("-details-"))));
await EnsureDetailsPageDataCachedAsync(relation).ConfigureAwait(false);
_supportCase.SupportCaseDataProviderArtifact.HealthCardDataHelper.UpdateNamedParameterEntries();
CaseDataChanged?.Invoke(this, new SupportCaseDataEventArgs());
}
public void ProcessComputations(cF4sdApiSearchResultRelation relation, IEnumerable<cHealthCardComputationBase> computations)
{
if (!_computationCache.ContainsKey(relation))
_computationCache.Add(relation, new Dictionary<string, IList<object>>());
var cachedComputations = _computationCache[relation];
var computationTables = new List<cF4SDHealthCardRawData.cHealthCardTable>();
foreach (cHealthCardComputationBase computation in computations)
{
AddComputationTable(computation);
AddComputationTableStatic(computation);
}
CaseDataChanged?.Invoke(this, new SupportCaseDataEventArgs() { Relation = relation, DataTables = computationTables });
void AddComputationTable(cHealthCardComputationBase computation)
{
var computationTable = new cF4SDHealthCardRawData.cHealthCardTable() { Name = $"Computation_{computation.Name}", AlternateStaticTable = $"Computation_{computation.Name}_latest" };
var computationColumn = new cF4SDHealthCardRawData.cHealthCardTableColumn(computationTable);
for (int i = 0; i < cF4SDCockpitXmlConfig.Instance.HealthCardConfig.SearchResultAge; i++)
{
object[] valuesRequiredToCompute = computation.Values
.Where(v => v.ValueTable != null && v.ValueColumn != null)
.Select(v => _supportCase.GetSupportCaseHealthcardData(relation, v, false)?.ElementAtOrDefault(i))
.ToArray();
object computedValue = computation.Compute(valuesRequiredToCompute);
computationColumn.Values.Add(computedValue);
}
computationTable.Columns = new Dictionary<string, cF4SDHealthCardRawData.cHealthCardTableColumn>() { ["default"] = computationColumn };
computationTables.Add(computationTable);
cachedComputations[computation.Name] = computationColumn.Values;
}
void AddComputationTableStatic(cHealthCardComputationBase computation)
{
var computationTableStatic = new cF4SDHealthCardRawData.cHealthCardTable() { Name = $"Computation_{computation.Name}_latest" };
var computationColumnStatic = new cF4SDHealthCardRawData.cHealthCardTableColumn(computationTableStatic);
object[] staticValuesRequiredToCompute = computation.Values
.Where(v => v.ValueTable != null && v.ValueColumn != null)
.Select(v => _supportCase.GetSupportCaseHealthcardData(relation, v, true)?.ElementAtOrDefault(0))
.ToArray();
object computedStaticValue = computation.Compute(staticValuesRequiredToCompute);
computationColumnStatic.Values.Add(computedStaticValue);
computationTableStatic.Columns = new Dictionary<string, cF4SDHealthCardRawData.cHealthCardTableColumn>() { ["default"] = computationColumnStatic };
computationTables.Add(computationTableStatic);
cachedComputations[$"{computation.Name}_latest"] = computationColumnStatic.Values;
}
}
public async Task UpdateLatestCaseDataFor(cF4sdApiSearchResultRelation relation)
{
try
{
int? agentUserId = relation.Identities.FirstOrDefault(i => i.Class == enumFasdInformationClass.User)?.agentId;
int? agentDeviceId = relation.Identities.FirstOrDefault(i => i.Class == enumFasdInformationClass.Computer)?.agentId;
await ActualizeDataAsync(agentUserId, agentDeviceId);
_supportCase.InvalidateLatestCaseDataCacheFor(relation, out var invalidatedTables);
_detailsPageDataCache.Remove(relation);
await _supportCase.LoadSupportCaseDataAsync(relation, invalidatedTables.Where(t => !t.Name.StartsWith("Computation_")).Select(t => t.Name));
}
catch (Exception ex)
{
LogException(ex);
}
}
private async Task<enumActualizeStatus> ActualizeDataAsync(int? agentUserId, int? agentDeviceId)
{
var status = enumActualizeStatus.unknown;
if (!agentUserId.HasValue && !agentDeviceId.HasValue)
return status;
try
{
TimeSpan refreshDelay = TimeSpan.FromMilliseconds(500);
const int maxPollCount = 20;
if (!agentDeviceId.HasValue)
{
LogEntry("Coudldn't acutalize data. There was no valid AgentDeviceId found.", LogLevels.Error);
return status;
}
var taskId = await cFasdCockpitCommunicationBase.Instance.ActualizeAgentData(agentDeviceId.Value, agentUserId);
if (taskId == Guid.Empty)
return enumActualizeStatus.failed;
enumFasdInformationClass informationClass = agentUserId != null ? enumFasdInformationClass.User : enumFasdInformationClass.Computer;
int pollCount = 0;
do
{
status = await cFasdCockpitCommunicationBase.Instance.GetActualizeAgentDataStatus(taskId, informationClass);
if (status == enumActualizeStatus.unknown)
{
pollCount++;
if (pollCount >= maxPollCount)
return status;
await Task.Delay(refreshDelay);
}
} while (status == enumActualizeStatus.unknown);
}
catch (Exception E)
{
LogException(E);
}
return status;
}
public ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> GetCaseRelations()
=> _supportCase.GetCaseRelations();
public cHealthCard GetHealthcardFor(cF4sdApiSearchResultRelation relation)
{
var availableHealthCards = cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.HealthCards?.Values;
if (availableHealthCards is null || availableHealthCards.Count == 0)
return null;
return availableHealthCards
.FirstOrDefault(hc =>
hc.InformationClasses.All(i => i == cF4sdIdentityEntry.GetFromSearchResult(relation.Type))
&& HasCockpitUserRequiredRoles(hc.RequiredRoles));
}
private static bool HasCockpitUserRequiredRoles(List<string> requiredRoles)
{
try
{
if (requiredRoles is null || requiredRoles.Count == 0)
return true;
List<string> roles = null;
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
{
roles = cFasdCockpitCommunicationBase.CockpitUserInfo?.Roles;
}
if (roles is null || roles.Count == 0)
return false;
foreach (var requiredRole in requiredRoles)
{
if (roles.Contains(requiredRole, StringComparer.InvariantCultureIgnoreCase))
return true;
}
}
catch (Exception E)
{
LogException(E);
}
return false;
}
public cDetailsPageDataHistoryDataModel GetHistoryData(cF4sdApiSearchResultRelation relation)
{
cDetailsPageDataHistoryDataModel historyData = null;
if (_detailsPageDataCache.TryGetValue(relation, out var detailsData))
historyData = detailsData?.DataHistoryList;
return historyData ?? new cDetailsPageDataHistoryDataModel();
}
public List<cContainerCollectionData> GetContainerData(cF4sdApiSearchResultRelation relation)
{
List<cContainerCollectionData> containerData = null;
if (_detailsPageDataCache.TryGetValue(relation, out var detailsData))
containerData = detailsData?.DataContainerCollectionList;
return containerData ?? new List<cContainerCollectionData>();
}
public CockpitValueDisplayData GetCockpitValueDisplayData(cHealthCardStateBase displayValueDefinition, cF4sdApiSearchResultRelation relation, bool getStatic)
{
IList<object> rawValues = GetRawValues(displayValueDefinition, relation, getStatic);
cHealthCardStateBase definitionForLevel = GetDefinitionForLevel(displayValueDefinition);
IList<enumHealthCardStateLevel> predefinedLevel = GetPredefinedLevels(displayValueDefinition, relation, getStatic);
cF4SDHealthCardRawData.cHealthCardDetailsTable valueDetailsTable = null;
if (displayValueDefinition?.Details is cHealthCardDetailsValued detailsValued)
valueDetailsTable = SupportCaseDetailsValueProcessesor.GetDetailsTable(rawValues?.FirstOrDefault(), detailsValued);
return new CockpitValueDisplayData()
{
IsLoading = false,
Title = displayValueDefinition?.Names.GetValue(),
Values = rawValues?.Select(raw => GetDisplayValue(raw, displayValueDefinition, valueDetailsTable)).ToList(),
Levels = predefinedLevel ?? rawValues?.Select(raw => GetLevel(raw, definitionForLevel, 0)).ToList(),
UiActions = GetValueUiActions(displayValueDefinition, valueDetailsTable)
};
}
private IList<object> GetRawValues(cHealthCardStateBase stateDefinition, cF4sdApiSearchResultRelation relation, bool getStatic)
{
const string computationPrefix = "Computation_";
if (stateDefinition?.DatabaseInfo?.ValueTable?.StartsWith(computationPrefix) ?? false)
if (_computationCache.TryGetValue(relation, out var cachedComputationValues))
if (cachedComputationValues.TryGetValue(stateDefinition.DatabaseInfo.ValueTable.Substring(computationPrefix.Length) + (getStatic ? "_latest" : string.Empty), out var computedValues))
return computedValues;
return _supportCase.GetSupportCaseHealthcardData(relation, stateDefinition.DatabaseInfo, getStatic);
}
private IList<cUiActionBase> GetValueUiActions(cHealthCardStateBase stateDefinition, cF4SDHealthCardRawData.cHealthCardDetailsTable detailedValueTable)
{
if (stateDefinition.Details is null)
return null;
List<cUiActionBase> uiActions = new List<cUiActionBase>(cF4SDCockpitXmlConfig.Instance.HealthCardConfig.SearchResultAge);
for (int i = 0; i < cF4SDCockpitXmlConfig.Instance.HealthCardConfig.SearchResultAge; i++)
{
uiActions.Add(new cShowDetailedDataAction(stateDefinition, i, detailedValueTable) { DisplayType = enumActionDisplayType.enabled });
}
return uiActions;
}
private IList<enumHealthCardStateLevel> GetHighestLevels(List<IList<enumHealthCardStateLevel>> allLevels, bool isNotTransparent)
{
var highestLevels = new List<enumHealthCardStateLevel>();
int maxLevelCount = allLevels?.Where(l => l != null).Select(l => l.Count).DefaultIfEmpty(0).Max() ?? 0;
for (int i = 0; i < maxLevelCount; i++)
{
enumHealthCardStateLevel highestLevel = enumHealthCardStateLevel.None;
foreach (var levels in allLevels)
{
if (levels == null || levels.Count <= i)
continue;
highestLevel = (enumHealthCardStateLevel)Math.Max((int)highestLevel, (int)levels[i]);
if (highestLevel == enumHealthCardStateLevel.Error)
break;
}
if (highestLevel <= enumHealthCardStateLevel.Ok)
highestLevel = isNotTransparent ? enumHealthCardStateLevel.Ok : enumHealthCardStateLevel.None;
highestLevels.Add(highestLevel);
}
return highestLevels;
}
private string GetDisplayValue(object rawValue, cHealthCardStateBase displayValueDefinition, cF4SDHealthCardRawData.cHealthCardDetailsTable detailedValueTable)
{
if (displayValueDefinition?.Details != null && detailedValueTable != null)
return SupportCaseDetailsValueProcessesor.GetDetailStringValue(displayValueDefinition.Details, detailedValueTable);
else if (displayValueDefinition is cHealthCardStateTranslation translationDefinition)
return GetTranslationValue(rawValue, translationDefinition);
else if (displayValueDefinition is cHealthCardStateAggregation)
return "Ø";
else
return cUtility.RawValueFormatter.GetDisplayValue(rawValue, displayValueDefinition.DisplayType);
}
private string GetTranslationValue(object rawValue, cHealthCardStateTranslation translationDefinition)
{
ITranslatorObject abstractTranslation = cF4SDHealthCardConfig.GetTranslationsWithName(translationDefinition, translationDefinition.Translation);
if (!(abstractTranslation is cHealthCardTranslator translation))
return null;
if (rawValue is null)
return translation.DefaultTranslation?.Translation?.GetValue();
string defaultValue = translation.DefaultTranslation?.Translation?.GetValue() ?? rawValue.ToString();
foreach (var translationEntry in translation.Translations)
{
if (translationEntry.Values.Any(v => string.Equals(rawValue.ToString(), v, StringComparison.InvariantCultureIgnoreCase)))
return translationEntry.Translation.GetValue();
}
return defaultValue;
}
private static enumHealthCardStateLevel GetLevel(object rawValue, cHealthCardStateBase stateDefinition, int referenceDays)
{
if (stateDefinition is null || rawValue is null)
return enumHealthCardStateLevel.None;
if (stateDefinition is cHealthCardStateAggregation)
throw new NotImplementedException();
try
{
if (stateDefinition is cHealthCardStateLevel levelDefinition)
{
var valueDouble = cF4SDHealthCardRawData.GetDouble(rawValue);
if (valueDouble != null)
{
if (levelDefinition.IsDirectionUp)
return valueDouble >= levelDefinition.Error ? enumHealthCardStateLevel.Error : valueDouble >= levelDefinition.Warning ? enumHealthCardStateLevel.Warning : stateDefinition.IsNotTransparent ? enumHealthCardStateLevel.Ok : enumHealthCardStateLevel.None;
else
return valueDouble <= levelDefinition.Error ? enumHealthCardStateLevel.Error : valueDouble <= levelDefinition.Warning ? enumHealthCardStateLevel.Warning : stateDefinition.IsNotTransparent ? enumHealthCardStateLevel.Ok : enumHealthCardStateLevel.None;
}
}
else if (stateDefinition is cHealthCardStateVersion stateVersion)
{
Version valueVersion = cF4SDHealthCardRawData.GetVersion(rawValue);
if (valueVersion is null)
return enumHealthCardStateLevel.None;
if (stateVersion.IsDirectionUp)
return valueVersion >= stateVersion.Error ? enumHealthCardStateLevel.Error : valueVersion >= stateVersion.Warning ? enumHealthCardStateLevel.Warning : stateDefinition.IsNotTransparent ? enumHealthCardStateLevel.Ok : enumHealthCardStateLevel.None;
else
return valueVersion <= stateVersion.Error ? enumHealthCardStateLevel.Error : valueVersion <= stateVersion.Warning ? enumHealthCardStateLevel.Warning : stateDefinition.IsNotTransparent ? enumHealthCardStateLevel.Ok : enumHealthCardStateLevel.None;
}
else if (stateDefinition is cHealthCardStateDateTime stateDateTime)
{
DateTime? valueDateTime = cF4SDHealthCardRawData.GetDateTime(rawValue);
if (valueDateTime is null)
return enumHealthCardStateLevel.None;
DateTime tempDateTime = valueDateTime.Value;
double differenceHours = Math.Floor((DateTime.UtcNow.AddDays(-referenceDays) - tempDateTime).TotalHours);
if (stateDateTime.IsDirectionUp)
return differenceHours >= stateDateTime.ErrorHours ? enumHealthCardStateLevel.Error : differenceHours >= stateDateTime.WarningHours ? enumHealthCardStateLevel.Warning : stateDefinition.IsNotTransparent ? enumHealthCardStateLevel.Ok : enumHealthCardStateLevel.None;
else
return differenceHours <= stateDateTime.ErrorHours ? enumHealthCardStateLevel.Error : differenceHours <= stateDateTime.WarningHours ? enumHealthCardStateLevel.Warning : stateDefinition.IsNotTransparent ? enumHealthCardStateLevel.Ok : enumHealthCardStateLevel.None;
}
else if (stateDefinition is cHealthCardStateInfo)
{
return stateDefinition.IsNotTransparent ? enumHealthCardStateLevel.Info : enumHealthCardStateLevel.None;
}
else if (stateDefinition is cHealthCardStateTranslation stateTranslation)
{
ITranslatorObject abstractTranslation = cF4SDHealthCardConfig.GetTranslationsWithName(stateTranslation, stateTranslation.Translation);
if (!(abstractTranslation is cHealthCardTranslator translation))
return enumHealthCardStateLevel.None;
enumHealthCardStateLevel translationStateLevel = translation.DefaultTranslation?.StateLevel ?? enumHealthCardStateLevel.Info;
foreach (var translationEntry in translation.Translations)
{
if (translationEntry.Values.Any(v => string.Equals(rawValue.ToString(), v, StringComparison.InvariantCultureIgnoreCase)))
translationStateLevel = translationEntry.StateLevel;
}
if (!stateTranslation.IsNotTransparent && (translationStateLevel == enumHealthCardStateLevel.Ok || translationStateLevel == enumHealthCardStateLevel.Info))
return enumHealthCardStateLevel.None;
else
return translationStateLevel;
}
else if (stateDefinition is cHealthCardStateRefLink)
{
throw new NotImplementedException();
}
return enumHealthCardStateLevel.None;
}
catch (Exception e)
{
LogException(e);
return enumHealthCardStateLevel.None;
}
}
public cUiActionBase GetUiAction(cHealthCardStateBase stateDefinition)
{
if (stateDefinition?.QuickActions is null || stateDefinition.QuickActions.Count == 0)
return null;
return stateDefinition.QuickActions.Count == 1
? GetSingleUiAction(stateDefinition)
: GetMultipleUiActions(stateDefinition);
}
private cHealthCardStateBase GetDefinitionForLevel(cHealthCardStateBase displayValueDefinition)
{
if (displayValueDefinition is cHealthCardStateRefLink stateRefLink)
return cF4SDHealthCardConfig.GetReferencableStateWithName(stateRefLink, stateRefLink.Reference);
return displayValueDefinition;
}
private IList<enumHealthCardStateLevel> GetPredefinedLevels(cHealthCardStateBase displayValueDefinition, cF4sdApiSearchResultRelation relation, bool getStatic)
{
if (displayValueDefinition is cHealthCardStateRefLink stateRefLink)
{
cHealthCardStateBase definition = cF4SDHealthCardConfig.GetReferencableStateWithName(stateRefLink, stateRefLink.Reference);
CockpitValueDisplayData displayData = GetCockpitValueDisplayData(definition, relation, getStatic);
return GetHighestLevels(new List<IList<enumHealthCardStateLevel>> { displayData.Levels }, stateRefLink.IsNotTransparent);
}
if (displayValueDefinition is cHealthCardStateAggregation stateAggregation)
{
List<IList<enumHealthCardStateLevel>> allLevels = stateAggregation.States.Select(s => GetCockpitValueDisplayData(s, relation, getStatic).Levels).ToList();
return GetHighestLevels(allLevels, stateAggregation.IsNotTransparent);
}
return null;
}
private cUiActionBase GetSingleUiAction(cHealthCardStateBase stateDefinition)
{
string quickActionName = stateDefinition.QuickActions?.FirstOrDefault();
if (string.IsNullOrWhiteSpace(quickActionName))
return null;
cUiActionBase uiAction = MenuDataFactory.GetByName(quickActionName, SupportCaseDataProviderArtifact.NamedParameterEntries, SupportCaseDataProviderArtifact.CaseRelations.Select(r => r.Key))?.UiAction;
if (uiAction is cUiQuickAction uiQuickAction)
uiQuickAction.QuickActionRecommendation = new cRecommendationDataModel { Category = quickActionName, Recommendation = stateDefinition.Descriptions.GetValue() };
return uiAction;
}
private cUiActionBase GetMultipleUiActions(cHealthCardStateBase stateDefinition)
{
List<cMenuDataBase> menuDatas = stateDefinition.QuickActions
.Select(quickActionName => MenuDataFactory.GetByName(quickActionName, SupportCaseDataProviderArtifact.NamedParameterEntries, SupportCaseDataProviderArtifact.CaseRelations.Select(r => r.Key)))
.Where(menuData => menuData?.UiAction != null)
.Select(menuData =>
{
if (menuData.UiAction is cUiQuickAction uiQuickAction)
uiQuickAction.QuickActionRecommendation = new cRecommendationDataModel
{
Category = stateDefinition.Names.GetValue(),
Recommendation = stateDefinition.Descriptions.GetValue()
};
return menuData;
})
.ToList();
if (menuDatas == null || menuDatas.Count == 0)
return null;
if (menuDatas.Count == 1)
return menuDatas[0].UiAction;
return new cSubMenuAction(false)
{
SubMenuData = menuDatas,
Name = stateDefinition.Names.GetValue(),
Description = stateDefinition.Descriptions.GetValue(),
DisplayType = enumActionDisplayType.enabled
};
}
public bool TryGetNamedParameterValue<T>(cF4sdApiSearchResultRelation relation, string parameterName, out T value)
{
value = default;
if (!_namedParameterCache.TryGetValue(relation, out var namedParameters))
return false;
if (!namedParameters.TryGetValue(parameterName, out var namedParameter))
return false;
try
{
value = (T)Convert.ChangeType(namedParameter, typeof(T));
}
catch
{
LogEntry($"Found named parameter, but can not be converted to type: {typeof(T)}. Value: {namedParameter} Actual type: {namedParameter.GetType()}", LogLevels.Info);
return false;
}
return true;
}
/// <summary>
/// Raised when newly available relations for a support case were added.
/// </summary>
public event EventHandler<RelationEventArgs> AvailableCaseRelationsAdded;
/// <summary>
/// Raised when the data set of a support case has changed.
/// </summary>
public event EventHandler<SupportCaseDataEventArgs> CaseDataChanged;
}
}

View File

@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
namespace FasdDesktopUi.Basics.Services.SupportCase
namespace FasdDesktopUi.Basics.Services.SupportCase.Processors
{
internal class SupportCaseProcessorFactory
{
private readonly static Dictionary<Guid, SupportCaseProcessor> _supportCaseProccesors = new Dictionary<Guid, SupportCaseProcessor>();
private readonly static Dictionary<Guid, ISupportCaseProcessor> _supportCaseProccesors = new Dictionary<Guid, ISupportCaseProcessor>();
internal static SupportCaseProcessor Get(Guid id)
internal static ISupportCaseProcessor Get(Guid id)
{
if (!_supportCaseProccesors.ContainsKey(id))
_supportCaseProccesors.Add(id, new SupportCaseProcessor());

View File

@@ -34,13 +34,19 @@ namespace FasdDesktopUi.Basics.Services.SupportCase
~SupportCase()
{
if (_relationService != null)
{
_relationService.RelationsReset -= HandleRelationsReset;
_relationService.RelationsFound -= HandleRelationsFound;
}
}
public void Initialize()
{
if (_relationService != null)
_relationService.RelationsFound += HandleRelationsFound;
if (_relationService is null)
return;
_relationService.RelationsReset += HandleRelationsReset;
_relationService.RelationsFound += HandleRelationsFound;
}
public ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> GetCaseRelations()
@@ -69,13 +75,13 @@ namespace FasdDesktopUi.Basics.Services.SupportCase
foreach (var relationType in relations)
{
if (_caseRelations.TryGetValue(relationType.Key, out var caseRelation))
caseRelation = caseRelation.Union(relationType).ToList();
if (_caseRelations.ContainsKey(relationType.Key))
_caseRelations[relationType.Key] = _caseRelations[relationType.Key].Union(relationType).ToList();
else
_caseRelations.Add(relationType.Key, relationType.ToList());
if (SupportCaseDataProviderArtifact?.CaseRelations?.TryGetValue(relationType.Key, out var caseRelations) ?? false)
caseRelations = caseRelations.Union(relationType).ToList();
if (SupportCaseDataProviderArtifact?.CaseRelations?.ContainsKey(relationType.Key) ?? false)
SupportCaseDataProviderArtifact.CaseRelations[relationType.Key] = SupportCaseDataProviderArtifact.CaseRelations[relationType.Key].Union(relationType).ToList();
else
SupportCaseDataProviderArtifact?.CaseRelations?.Add(relationType.Key, relationType.ToList());
}
@@ -134,7 +140,6 @@ namespace FasdDesktopUi.Basics.Services.SupportCase
UpdateSupportCaseDataCache(relation, rawData?.Tables?.Values);
isDataComplete = rawData?.Tables?
.Where(table => table.Key.StartsWith("Computation_") == false)
.All(table => !table.Value.IsIncomplete && !table.Value.Columns.Values.Any(c => c.IsIncomplete)) ?? false;
}
@@ -279,15 +284,25 @@ namespace FasdDesktopUi.Basics.Services.SupportCase
}
}
public IEnumerable<object> GetSupportCaseHealthcardData(cF4sdApiSearchResultRelation relation, cValueAddress valueAddress)
public IList<object> GetSupportCaseHealthcardData(cF4sdApiSearchResultRelation relation, cValueAddress valueAddress, bool getStatic)
{
try
{
if (!_supportCaseDataCache.TryGetValue(valueAddress.ValueTable, out var tables))
if (!TryGetTable(relation, valueAddress, out var table))
return null;
if (!tables.TryGetValue(relation, out var table))
return null;
if (getStatic && !string.IsNullOrEmpty(table.AlternateStaticTable))
{
cValueAddress staticValueAdress = new cValueAddress()
{
DayIndex = valueAddress.DayIndex,
ValueTable = table.AlternateStaticTable,
ValueColumn = valueAddress.ValueColumn
};
if (TryGetTable(relation, staticValueAdress, out var staticTable))
table = staticTable;
}
if (!table.Columns.TryGetValue(valueAddress.ValueColumn, out var column))
return null;
@@ -302,6 +317,28 @@ namespace FasdDesktopUi.Basics.Services.SupportCase
return null;
}
private bool TryGetTable(cF4sdApiSearchResultRelation relation, cValueAddress valueAddress, out cF4SDHealthCardRawData.cHealthCardTable table)
{
table = null;
if (valueAddress is null)
return false;
if (!_supportCaseDataCache.TryGetValue(valueAddress.ValueTable, out var tables))
return false;
if (!tables.TryGetValue(relation, out table))
return false;
return true;
}
private void HandleRelationsReset(object sender, EventArgs e)
{
_caseRelations.Clear();
AddCaseRelations(_relationService?.GetLoadedRelations());
}
private void HandleRelationsFound(object sender, StagedSearchResultRelationsEventArgs e)
{
AddCaseRelations(e.StagedResultRelations.Relations);

View File

@@ -1,281 +0,0 @@
using C4IT.FASD.Base;
using C4IT.FASD.Cockpit.Communication;
using C4IT.Logging;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Pages.DetailsPage.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.Services.SupportCase
{
/// <summary>
/// Used for processing raw data of a <see cref="ISupportCase"/> for the UI in a certain way.
/// </summary>
internal class SupportCaseProcessor
{
private ISupportCase _supportCase;
public cSupportCaseDataProvider SupportCaseDataProviderArtifact { get => _supportCase?.SupportCaseDataProviderArtifact; }
private readonly Dictionary<cF4sdApiSearchResultRelation, cDetailsPageData> _detailsPageDataCache = new Dictionary<cF4sdApiSearchResultRelation, cDetailsPageData>();
private readonly Dictionary<cF4sdApiSearchResultRelation, Dictionary<string, object>> _namedParameterCache = new Dictionary<cF4sdApiSearchResultRelation, Dictionary<string, object>>();
internal void SetSupportCase(ISupportCase supportCase)
{
if (_supportCase != null)
{
_supportCase.CaseRelationsAdded -= HandleSupportCaseRelationsAdded;
_supportCase.SupportCaseDataCacheHasChanged -= HandleSupportCaseDataCacheHasChanged;
}
_supportCase = supportCase;
_supportCase.CaseRelationsAdded += HandleSupportCaseRelationsAdded;
_supportCase.SupportCaseDataCacheHasChanged += HandleSupportCaseDataCacheHasChanged;
}
private void HandleSupportCaseRelationsAdded(object sender, RelationEventArgs e)
=> AvailableCaseRelationsAdded?.Invoke(this, e);
private async void HandleSupportCaseDataCacheHasChanged(object sender, SupportCaseDataEventArgs e)
{
bool isArtifactShowingCorrectHealthCard
= SupportCaseDataProviderArtifact.HealthCardDataHelper.SelectedHealthCard == GetHealthcardFor(e.Relation);
if (!isArtifactShowingCorrectHealthCard)
{
// todo this can probably be removed, as soon as the last dependency of the SupportCaseDataProviderArtifact is gone.
// till then the detailspageData gets overriden with the detailspageData of the new relation.
// However, the removal shouldn't be much of a problem, due to the fact the Artifact also stores the raw data
_detailsPageDataCache.Remove(e.Relation);
return;
}
if (_detailsPageDataCache.TryGetValue(e.Relation, out var cachedData))
{
cDetailsPageData detailData = _supportCase.SupportCaseDataProviderArtifact.HealthCardDataHelper.DetailPage.GetDataWithoutHeading();
cachedData.WidgetData = detailData.WidgetData;
cachedData.DataHistoryList = detailData.DataHistoryList;
cachedData.MenuBarData = detailData.MenuBarData;
cachedData.DataContainerCollectionList = detailData.DataContainerCollectionList;
}
else
{
_detailsPageDataCache[e.Relation] = await _supportCase.SupportCaseDataProviderArtifact.HealthCardDataHelper.DetailPage.GetDataAsync();
}
UpdateNamedParameters(e.Relation, e.DataTables);
CaseDataChanged?.Invoke(this, e);
}
private void UpdateNamedParameters(cF4sdApiSearchResultRelation relation, IEnumerable<cF4SDHealthCardRawData.cHealthCardTable> dataTables)
{
try
{
if (!_namedParameterCache.ContainsKey(relation))
_namedParameterCache.Add(relation, new Dictionary<string, object>());
var healthcard = GetHealthcardFor(relation);
foreach (var namedParameter in cHealthCardPrerequisites.GetNamedParameters(healthcard).Values)
{
var table = dataTables.FirstOrDefault(t => t.Name == namedParameter.DatabaseInfo.ValueTable);
if (table is null)
continue;
if (!table.Columns.TryGetValue(namedParameter.DatabaseInfo.ValueColumn, out var column))
continue;
string value = cUtility.RawValueFormatter.GetDisplayValue(column.Values.FirstOrDefault(), namedParameter.Display);
_namedParameterCache[relation][namedParameter.ParameterName] = value;
}
}
catch (Exception ex)
{
LogException(ex);
}
}
public async Task LoadSupportCaseDataAsync(cF4sdApiSearchResultRelation relation, IEnumerable<string> tablesToLoad)
{
_ = Task.Run(async () => await _supportCase.LoadSupportCaseDataAsync(relation, tablesToLoad.Where(t => !t.Contains("-details-"))));
if (!_detailsPageDataCache.TryGetValue(relation, out var detailsData))
{
detailsData = await _supportCase.SupportCaseDataProviderArtifact.HealthCardDataHelper.DetailPage.GetDataAsync();
_detailsPageDataCache.Add(relation, detailsData);
}
else
{
_supportCase.SupportCaseDataProviderArtifact.HealthCardDataHelper.UpdateNamedParameterEntries();
}
CaseDataChanged?.Invoke(this, new SupportCaseDataEventArgs());
}
public async Task UpdateLatestCaseDataFor(cF4sdApiSearchResultRelation relation)
{
try
{
int? agentUserId = relation.Identities.FirstOrDefault(i => i.Class == enumFasdInformationClass.User)?.agentId;
int? agentDeviceId = relation.Identities.FirstOrDefault(i => i.Class == enumFasdInformationClass.Computer)?.agentId;
await ActualizeDataAsync(agentUserId, agentDeviceId);
_supportCase.InvalidateLatestCaseDataCacheFor(relation, out var invalidatedTables);
_detailsPageDataCache.Remove(relation);
await _supportCase.LoadSupportCaseDataAsync(relation, invalidatedTables.Where(t => !t.Name.StartsWith("Computation_")).Select(t => t.Name));
}
catch (Exception ex)
{
LogException(ex);
}
}
private async Task<enumActualizeStatus> ActualizeDataAsync(int? agentUserId, int? agentDeviceId)
{
var status = enumActualizeStatus.unknown;
if (!agentUserId.HasValue && !agentDeviceId.HasValue)
return status;
try
{
TimeSpan refreshDelay = TimeSpan.FromMilliseconds(500);
const int maxPollCount = 20;
if (!agentDeviceId.HasValue)
{
LogEntry("Coudldn't acutalize data. There was no valid AgentDeviceId found.", LogLevels.Error);
return status;
}
var taskId = await cFasdCockpitCommunicationBase.Instance.ActualizeAgentData(agentDeviceId.Value, agentUserId);
if (taskId == Guid.Empty)
return enumActualizeStatus.failed;
enumFasdInformationClass informationClass = agentUserId != null ? enumFasdInformationClass.User : enumFasdInformationClass.Computer;
int pollCount = 0;
do
{
status = await cFasdCockpitCommunicationBase.Instance.GetActualizeAgentDataStatus(taskId, informationClass);
if (status == enumActualizeStatus.unknown)
{
pollCount++;
if (pollCount >= maxPollCount)
return status;
await Task.Delay(refreshDelay);
}
} while (status == enumActualizeStatus.unknown);
}
catch (Exception E)
{
LogException(E);
}
return status;
}
internal ILookup<enumFasdInformationClass, cF4sdApiSearchResultRelation> GetCaseRelations()
=> _supportCase.GetCaseRelations();
internal cHealthCard GetHealthcardFor(cF4sdApiSearchResultRelation relation)
{
var availableHealthCards = cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.HealthCards?.Values;
if (availableHealthCards is null || availableHealthCards.Count == 0)
return null;
return availableHealthCards
.FirstOrDefault(hc =>
hc.InformationClasses.All(i => i == cF4sdIdentityEntry.GetFromSearchResult(relation.Type))
&& HasCockpitUserRequiredRoles(hc.RequiredRoles));
}
private static bool HasCockpitUserRequiredRoles(List<string> requiredRoles)
{
try
{
if (requiredRoles is null || requiredRoles.Count == 0)
return true;
List<string> roles = null;
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
{
roles = cFasdCockpitCommunicationBase.CockpitUserInfo?.Roles;
}
if (roles is null || roles.Count == 0)
return false;
foreach (var requiredRole in requiredRoles)
{
if (roles.Contains(requiredRole, StringComparer.InvariantCultureIgnoreCase))
return true;
}
}
catch (Exception E)
{
LogException(E);
}
return false;
}
public List<List<cWidgetValueModel>> GetWidgetData(cF4sdApiSearchResultRelation relation)
{
List<List<cWidgetValueModel>> widgetData = null;
if (_detailsPageDataCache.TryGetValue(relation, out var detailsData))
widgetData = detailsData?.WidgetData;
return widgetData ?? new List<List<cWidgetValueModel>>();
}
public cDetailsPageDataHistoryDataModel GetHistoryData(cF4sdApiSearchResultRelation relation)
{
cDetailsPageDataHistoryDataModel historyData = null;
if (_detailsPageDataCache.TryGetValue(relation, out var detailsData))
historyData = detailsData?.DataHistoryList;
return historyData ?? new cDetailsPageDataHistoryDataModel();
}
public List<cContainerCollectionData> GetContainerData(cF4sdApiSearchResultRelation relation)
{
List<cContainerCollectionData> containerData = null;
if (_detailsPageDataCache.TryGetValue(relation, out var detailsData))
containerData = detailsData?.DataContainerCollectionList;
return containerData ?? new List<cContainerCollectionData>();
}
public List<cMenuDataBase> GetMenuBarData(cF4sdApiSearchResultRelation relation)
{
List<cMenuDataBase> menuData = null;
if (_detailsPageDataCache.TryGetValue(relation, out var detailsData))
menuData = detailsData?.MenuBarData;
return menuData ?? new List<cMenuDataBase>();
}
/// <summary>
/// Raised when newly available relations for a support case were added.
/// </summary>
public event EventHandler<RelationEventArgs> AvailableCaseRelationsAdded;
/// <summary>
/// Raised when the data set of a support case has changed.
/// </summary>
public event EventHandler<SupportCaseDataEventArgs> CaseDataChanged;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -28,6 +28,9 @@ using FasdDesktopUi.Basics.Services.SupportCase;
using FasdDesktopUi.Basics.Services.RelationService;
using FasdDesktopUi.Basics.Services.SupportCase.Controllers;
using C4IT.F4SD.SupportCaseProtocoll.Models;
using FasdDesktopUi.Basics.Services.SupportCase.Processors;
using F4SD.Gamification;
using F4SD.Gamification.Services;
namespace FasdDesktopUi.Basics
@@ -178,7 +181,7 @@ namespace FasdDesktopUi.Basics
return null;
HashSet<string> requiredTables = cHealthCard.GetRequiredTables(_result.HealthCardDataHelper.SelectedHealthCard); // todo the healthcard is not selected at this point
detailsPage.WidgetCollection.WidgetDataList = supportCaseController.GetWidgetData();
detailsPage.WidgetCollection.WidgetDataList = supportCaseController.GetWidgetsData();
detailsPage.DataHistoryCollectionUserControl.HistoryDataList = supportCaseController.GetHistoryData();
detailsPage.CustomizableSectionUc.ContainerCollections = supportCaseController.GetContainerData();
@@ -269,6 +272,7 @@ namespace FasdDesktopUi.Basics
TimerView.ResetTimer();
CaseChanged?.Invoke(this, new EventArgs());
GamificationService.TrackAction(CockpitAction.CaseOpened);
}
catch (Exception E)
{
@@ -308,7 +312,7 @@ namespace FasdDesktopUi.Basics
var nettoTime = workTimes["NettoWorkingTime"];
var caseParameter = new cF4SDCaseStatusParameters() { CaseId = tempCaseId, StatusId = CaseStatus.Finished, ActiveTime = (double)nettoTime };
tasks.Add(cFasdCockpitCommunicationBase.Instance.UpdateCase(caseParameter, TimerView.caseTimes));
tasks.Add(cFasdCockpitCommunicationBase.Instance.UpdateCase(caseParameter, TimerView.CaseTimes));
caseAliveTimer?.Stop();
caseAliveTimer?.Dispose();
}

View File

@@ -0,0 +1,171 @@
using C4IT.F4SD.DisplayFormatting;
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using FasdCockpitBase.Models.RemoteDesktopConnection;
using FasdCockpitCommunication.RemoteDesktopCommunication;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.RemoteDesktop;
using FasdDesktopUi.Basics.UserControls;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UiActions.NativeActions
{
internal class RemoteConnectionAction
{
internal const string NativeActionName = "StartAgentRemoteConnection";
internal static void UpdatePrerequesites(FasdNativeQuickAction nativeQuickAction)
{
nativeQuickAction.CheckFilePath = AgentRemoteDesktopService.GetViewerPath();
}
internal static cDataCanvasDataModel GetQuickActionData(cFasdQuickAction quickActionConfig, cQuickActionStatusMonitorModel.RunQuickActionDelegate quickAction)
{
var detailedDataQuickActionHistory = new cDetailedDataModel()
{
Heading = cMultiLanguageSupport.GetItem("DetailsPage.History"),
FullDetailedData = new List<object>() { new List<object>() { "Status", cMultiLanguageSupport.GetItem("QuickAction.Revision.ExecutionTime") } }
};
return new cDataCanvasDataModel()
{
RecommendationData = null,
QuickActionStatusMonitorData = new cQuickActionStatusMonitorModel()
{
ActionName = quickActionConfig.Names.GetValue(),
ActionSteps = new List<cQuickActionStatusMonitorModel.cQuickActionStep>()
{
new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Remote.UserAcceptance"), quickActionConfig.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.waitingForUserAcceptance),
new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Phoenix.StartViewer"), quickActionConfig.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running)
},
QuickActionDefinition = quickActionConfig,
RunQuickAction = quickAction
},
DetailedData = detailedDataQuickActionHistory,
};
}
private static bool TryGetNamedParameterValue(cNamedParameterList namedParameters, string namedParameterName, string quickActionName, QuickActionStatusMonitor statusMonitor, out int namedParameterValue)
{
namedParameterValue = -1;
bool hasNamedParameterValue = true;
if (!namedParameters.TryGetValue(namedParameterName, out var namedParameter))
{
cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(statusMonitor.QuickActionData.ActionSteps);
statusMonitor.QuickActionOutputs.Add(new cF4sdQuickActionRevision.cOutput() { Values = $"Named parameter \"{namedParameterName}\" is missing. Try to refresh data." });
hasNamedParameterValue = false;
}
if (!int.TryParse(namedParameter.GetValue(), out namedParameterValue))
{
cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(statusMonitor.QuickActionData.ActionSteps);
statusMonitor.QuickActionOutputs.Add(new cF4sdQuickActionRevision.cOutput() { Values = $"Named parameter \"{namedParameterName}\" is missing. Try to refresh data." });
hasNamedParameterValue = false;
}
return hasNamedParameterValue;
}
private static bool TryGetClientInfo(string quickActionName, QuickActionStatusMonitor statusMonitor, cNamedParameterList namedParameters, out AgentRemoteClientInfo clientInfo)
{
clientInfo = null;
try
{
bool hasClientInfo = true;
if (!TryGetNamedParameterValue(namedParameters, "AgentUserId", quickActionName, statusMonitor, out var userId))
hasClientInfo = false;
if (!TryGetNamedParameterValue(namedParameters, "AgentDeviceId", quickActionName, statusMonitor, out var deviceId))
hasClientInfo = false;
int? organizationId = cCockpitConfiguration.Instance?.agentApiConfiguration?.OrganizationCode;
if (organizationId is null)
{
cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(statusMonitor.QuickActionData.ActionSteps);
hasClientInfo = false;
}
clientInfo = new AgentRemoteClientInfo() { AccountCode = userId, DeviceCode = deviceId, OrganisationCode = organizationId.Value };
return hasClientInfo;
}
catch (Exception ex)
{
LogException(ex);
return false;
}
}
internal static async Task<List<object>> RunQuickAction(string quickActionName, QuickActionStatusMonitor statusMonitor, cNamedParameterList namedParameters, CancellationToken token)
{
try
{
statusMonitor.QuickActionOutputs.Clear();
var errorOutput = new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), cUtility.RawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
if (!TryGetClientInfo(quickActionName, statusMonitor, namedParameters, out var clientInfo))
return errorOutput;
AgentRemoteDesktopService.RemoteConnetionStatusChanged += HandleConnectionStatusChanged;
RemoteDesktopConnectionStatusResult connectionStatus = await AgentRemoteDesktopService.StartRemoteDesktopConnectionAsync(clientInfo, true, token);
switch (connectionStatus.Status)
{
case RemoteDesktopConnectionStatus.Accepted:
case RemoteDesktopConnectionStatus.Connected:
case RemoteDesktopConnectionStatus.Finished:
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(statusMonitor?.QuickActionData?.ActionSteps, quickActionName, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.waitingForUserAcceptance, enumQuickActionRevisionStatus.finishedSuccessfull);
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull"), cUtility.RawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
case RemoteDesktopConnectionStatus.Canceled:
cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(statusMonitor?.QuickActionData?.ActionSteps);
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Canceled"), cUtility.RawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
case RemoteDesktopConnectionStatus.Error:
foreach (var error in connectionStatus.Errors)
{
var quickactionOutput = new cF4sdQuickActionRevision.cOutput() { Values = error };
statusMonitor.QuickActionOutputs.Add(quickactionOutput);
}
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(statusMonitor?.QuickActionData?.ActionSteps, quickActionName, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.waitingForUserAcceptance, enumQuickActionRevisionStatus.finishedWithError);
return new List<object>() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), cUtility.RawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
default:
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(statusMonitor?.QuickActionData?.ActionSteps, quickActionName, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.waitingForUserAcceptance, enumQuickActionRevisionStatus.finishedWithError);
return errorOutput;
}
}
finally
{
AgentRemoteDesktopService.RemoteConnetionStatusChanged -= HandleConnectionStatusChanged;
}
void HandleConnectionStatusChanged(object sender, RemoteDesktopConnectionStatus e)
{
switch (e)
{
case RemoteDesktopConnectionStatus.Accepted:
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(statusMonitor?.QuickActionData?.ActionSteps, quickActionName, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.waitingForUserAcceptance, enumQuickActionRevisionStatus.finishedSuccessfull);
break;
case RemoteDesktopConnectionStatus.Connected:
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(statusMonitor?.QuickActionData?.ActionSteps, quickActionName, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running, enumQuickActionRevisionStatus.finishedSuccessfull);
break;
case RemoteDesktopConnectionStatus.Canceled:
cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(statusMonitor?.QuickActionData?.ActionSteps);
break;
default:
break;
}
}
}
}
}

View File

@@ -337,7 +337,7 @@ namespace FasdDesktopUi.Basics.UiActions
shouldHideRow = true;
}
cUtility.RawValueFormatter.SetDefaultCulture(new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
cUtility.RawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
foreach (var index in rawColumnIndexes)

View File

@@ -1,13 +1,7 @@
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;
@@ -19,7 +13,7 @@ namespace FasdDesktopUi.Basics.UiActions
public class cSubMenuAction : cUiActionBase
{
public bool UseTempData { get; private set; }
public List<cMenuDataBase> SubMenuData { get; set; }
public List<cMenuDataBase> SubMenuData { get; set; } = new List<cMenuDataBase>();
public cSubMenuAction(bool UseTempData)
{

View File

@@ -30,6 +30,8 @@ namespace FasdDesktopUi.Basics.UiActions
return new cUiDemoQuickAction(QuickActionDemo);
else if (quickAction is cF4sdQuickActionServer serverQuickAction)
return new cUiServerQuickAction(serverQuickAction);
else if (quickAction is FasdNativeQuickAction nativeQuickAction)
return new UiNativeQuickAction(nativeQuickAction);
else
return new cUiDummyQuickAction(quickAction);
}

View File

@@ -6,6 +6,8 @@ using System.Windows;
using FasdDesktopUi.Basics.UserControls;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using F4SD.Gamification;
using F4SD.Gamification.Services;
namespace FasdDesktopUi.Basics.UiActions
{
@@ -36,6 +38,8 @@ namespace FasdDesktopUi.Basics.UiActions
if (sender is CustomMenuItem senderElement)
await cUtility.ChangeIconToCheckAsync(senderElement.MenuItemIcon);
GamificationService.TrackAction(CockpitAction.CopyTemplateClicked);
return true;
}
catch (Exception E)

View File

@@ -78,6 +78,9 @@ namespace FasdDesktopUi.Basics.UiActions
public override async Task<List<object>> ProcessActionAsync(CancellationToken token, Dictionary<cAdjustableParameter, object> ParameterDictionary = null)
{
var runningId = Guid.NewGuid();
StatusMonitor.CurrentRunningQuickActionId = runningId;
var _finshedStatus = enumQuickActionRevisionStatus.finishedSuccessfull;
if (quickActionDemo.SimulatedClientConnect > 0)
{
@@ -86,7 +89,7 @@ namespace FasdDesktopUi.Basics.UiActions
if (token.IsCancellationRequested)
_finshedStatus = enumQuickActionRevisionStatus.canceled;
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, quickActionDemo.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.connectingToClient, _finshedStatus);
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor?.QuickActionData?.ActionSteps, quickActionDemo.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.connectingToClient, _finshedStatus);
}
if (quickActionDemo.SimulatedRuntime > 0)
@@ -98,14 +101,16 @@ namespace FasdDesktopUi.Basics.UiActions
if (token.IsCancellationRequested)
_finshedStatus = enumQuickActionRevisionStatus.canceled;
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, quickActionDemo.Name, cQuickActionStatusMonitorModel.cQuickActionStep.enumActionStepType.running, _finshedStatus);
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);
if (StatusMonitor.CurrentRunningQuickActionId == runningId)
cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(StatusMonitor.QuickActionData.ActionSteps);
}
else
{

View File

@@ -133,8 +133,8 @@ namespace FasdDesktopUi.Basics.UiActions
{
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);
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 });
@@ -182,8 +182,8 @@ namespace FasdDesktopUi.Basics.UiActions
}
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);
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") });

View File

@@ -100,8 +100,8 @@ namespace FasdDesktopUi.Basics.UiActions
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);
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"), cUtility.RawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) };
}
@@ -112,8 +112,8 @@ namespace FasdDesktopUi.Basics.UiActions
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);
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 });
@@ -134,8 +134,8 @@ namespace FasdDesktopUi.Basics.UiActions
}
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);
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") });

View File

@@ -0,0 +1,49 @@
using C4IT.FASD.Base;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions.NativeActions;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace FasdDesktopUi.Basics.UiActions
{
internal class UiNativeQuickAction : cUiQuickAction
{
private readonly string _nativeActionName;
public UiNativeQuickAction(FasdNativeQuickAction quickActionConfig) : base(quickActionConfig)
{
_nativeActionName = quickActionConfig.NativeName;
}
public override Task<cDataCanvasDataModel> GetQuickActionDataAsync(cSupportCaseDataProvider dataProvider, bool isDetailedLayout)
{
DataProvider = dataProvider;
switch (_nativeActionName)
{
case RemoteConnectionAction.NativeActionName:
return Task.FromResult(RemoteConnectionAction.GetQuickActionData(QuickActionConfig, ProcessActionAsync));
default:
throw new NotImplementedException();
}
}
public override async Task<List<object>> ProcessActionAsync(CancellationToken token, Dictionary<cAdjustableParameter, object> parameterDictionary = null)
{
return await RunNativeAction(_nativeActionName, token);
}
private async Task<List<object>> RunNativeAction(string actionName, CancellationToken token)
{
switch (actionName)
{
case RemoteConnectionAction.NativeActionName:
return await RemoteConnectionAction.RunQuickAction(QuickActionConfig.Name, StatusMonitor, DataProvider?.NamedParameterEntries, token);
default:
throw new NotImplementedException();
}
}
}
}

View File

@@ -33,14 +33,11 @@ namespace FasdDesktopUi.Basics.UiActions
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);
HistoryEntry.SearchUiProvider.ShowSearchRelations(SearchEntry, HistoryEntry.RelationService, HistoryEntry.SearchUiProvider);
return true;
case cSearchHistoryRelationEntry RelationEntry:
string caseObjectName = RelationEntry.SelectedRelation.DisplayName;
@@ -58,7 +55,7 @@ namespace FasdDesktopUi.Basics.UiActions
}
}
HistoryEntry.isSeen = true;
dataProvider = await cSupportCaseDataProvider.GetDataProviderForAsync(RelationEntry.SelectedRelation, relationService);
dataProvider = await cSupportCaseDataProvider.GetDataProviderForAsync(RelationEntry.SelectedRelation, HistoryEntry.RelationService);
if (dataProvider is null)
{
Debug.Assert(true, "Could not start a data provider for the selected criterias.");

View File

@@ -1,12 +1,12 @@
using C4IT.FASD.Base;
using C4IT.Logging;
using C4IT.MultiLanguage;
using FasdDesktopUi.Basics.Helper;
using C4IT.MultiLanguage;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Services.RelationService;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
@@ -61,21 +61,21 @@ namespace FasdDesktopUi.Basics.UiActions
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;
}
if (TicketDeepLinkHelper.TryOpenTicketRelationExternally(_selectedRelation))
return false;
// check, if have an active support case
var supportCaseActive = dataProvider?.IsActive ?? 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;
}
if (TicketExternalLinkHelper.TryOpenTicketRelationExternally(_selectedRelation))
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);
var _seachHistoryEntry = new cSearchHistoryRelationEntry(Name, _selectedSearchResult, _relations, _selectedRelation, _searchUiProvider, _relationService);
cSearchManager.Instance.ReplaceEntry(_seachHistoryEntry, _searchHistoryEntry);
// show the loading information
@@ -96,9 +96,12 @@ namespace FasdDesktopUi.Basics.UiActions
// get the new data provider for the support call informations (get it from the cache or create a new one)
dataProvider = await cSupportCaseDataProvider.GetDataProviderForAsync(_selectedRelation, _relationService);
bool shouldLoadRelationsForSelectedRelation = _selectedRelation.Type == enumF4sdSearchResultClass.User;
if (shouldLoadRelationsForSelectedRelation)
StartLoadingRelationsFor(_selectedRelation);
bool shouldLoadRelationsForSelectedRelation = _selectedRelation.Type == enumF4sdSearchResultClass.User;
if (shouldLoadRelationsForSelectedRelation)
{
_relationService.Reset();
StartLoadingRelationsFor(_selectedRelation);
}
if (dataProvider is null)
{

View File

@@ -116,7 +116,7 @@ namespace FasdDesktopUi.Basics.UiActions
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);
var relationSearchResult = new cSearchHistorySearchResultEntry(_searchResults.FirstOrDefault().DisplayName, _searchResults.FirstOrDefault().Name, _searchResults, caseRelations, _searchUiProvider, _relationService);
string displayName = !string.IsNullOrWhiteSpace(selectedRelation?.Name) ? $"{name} → {selectedRelation.Name}" : name;
cUiProcessSearchRelationAction action

View File

@@ -44,7 +44,7 @@ namespace FasdDesktopUi.Basics.UiActions
if (QuickActionConfig is null)
return;
cUtility.RawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
cUtility.RawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
shouldRunImmidiate = QuickActionConfig.RunImmediate;

View File

@@ -85,6 +85,9 @@ namespace FasdDesktopUi.Basics.UiActions
{
try
{
var runningId = Guid.NewGuid();
StatusMonitor.CurrentRunningQuickActionId = runningId;
int agentDeviceId = int.MinValue;
int? agentUserIdNullable = null;
var startTime = DateTime.UtcNow;
@@ -132,11 +135,12 @@ namespace FasdDesktopUi.Basics.UiActions
if (!token.IsCancellationRequested)
{
StatusMonitor.QuickActionOutputs.Add(QuickActionResult.Output);
if (StatusMonitor.CurrentRunningQuickActionId == runningId)
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);
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor?.QuickActionData?.ActionSteps, RemoteQuickAction.Name, enumActionStepType.running, status);
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor?.QuickActionData?.ActionSteps, RemoteQuickAction.Name, enumActionStepType.main, status);
cQuickActionCopyData copyData = QuickActionProtocollEntryOutput.GetCopyData(RemoteQuickAction, DataProvider, true, protocollOutput, StatusMonitor.MeasureValues);
QuickActionProtocollEntry protocollEntry = QuickActionProtocollEntryOutput.GetQuickActionProtocollEntry(RemoteQuickAction, copyData);
@@ -145,7 +149,8 @@ namespace FasdDesktopUi.Basics.UiActions
}
else
{
cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(StatusMonitor.QuickActionData.ActionSteps);
if (StatusMonitor.CurrentRunningQuickActionId == runningId)
cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(StatusMonitor.QuickActionData.ActionSteps);
quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") });
@@ -303,7 +308,7 @@ namespace FasdDesktopUi.Basics.UiActions
foreach (var actionStepToUpdate in actionStepsToUpdate)
{
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, RemoteQuickAction.Name, actionStepToUpdate, enumQuickActionRevisionStatus.finishedSuccessfull);
cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor?.QuickActionData?.ActionSteps, RemoteQuickAction.Name, actionStepToUpdate, enumQuickActionRevisionStatus.finishedSuccessfull);
}
if (quickActionStatus == enumQuickActionStatus.Finished || quickActionStatus == enumQuickActionStatus.Cancelled)

View File

@@ -134,8 +134,8 @@ namespace FasdDesktopUi.Basics.UiActions
{
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);
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
@@ -198,8 +198,8 @@ namespace FasdDesktopUi.Basics.UiActions
}
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);
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") });

View File

@@ -21,7 +21,8 @@
MouseLeftButtonUp="MenuItemBorder_Click"
TouchDown="MenuItemBorder_Click"
MouseEnter="MenuItemBorder_MouseEnter"
MouseLeave="MenuItemBorder_MouseLeave">
MouseLeave="MenuItemBorder_MouseLeave"
>
<Grid x:Name="MenuItemContent">
<Grid.ColumnDefinitions>
@@ -31,12 +32,14 @@
</Grid.ColumnDefinitions>
<ico:AdaptableIcon x:Name="MenuItemIcon"
Grid.Column="0" />
Grid.Column="0"
/>
<ico:AdaptableIcon x:Name="MenuItemOverlayIcon"
Grid.Column="0"
BorderPadding="10 10 0 0"
Margin="0 0 -5 -5"/>
Visibility="Collapsed"
IsHitTestVisible="False"
/>
<StackPanel Grid.Column="1"
Margin="15 0 15 0"

View File

@@ -1,186 +1,207 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using FasdDesktopUi.Basics.Converter;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using MaterialIcons;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class CustomMenuItem : UserControl
{
#region Properties
#region MenuData
private cMenuDataBase _menuData = new cMenuDataBase();
private readonly bool _isLean;
public cMenuDataBase MenuData
{
get { return _menuData; }
set
{
if (_menuData != value)
{
_menuData = value;
MenuDataChanged();
}
}
}
private void MenuDataChanged()
{
if (MenuData.MenuIcon.Intern != null)
MenuItemIcon.SelectedInternIcon = MenuData.MenuIcon.Intern;
else if (MenuData.MenuIcon.Material != null)
MenuItemIcon.SelectedMaterialIcon = MenuData.MenuIcon.Material;
MenuItemIcon.IconHeight = MenuData.MenuIconSize * MenuItemIcon.IconHeight;
MenuItemIcon.IconWidth = MenuData.MenuIconSize * MenuItemIcon.IconWidth;
switch (MenuData.UiAction?.DisplayType)
{
case Enums.enumActionDisplayType.hidden:
//todo: add hidden state
break;
case Enums.enumActionDisplayType.disabled:
MenuItemContent.SetValue(OpacityProperty, 0.5);
MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory.NoHover");
MenuItemBorder.SetValue(ToolTipProperty, string.IsNullOrWhiteSpace(MenuData.UiAction.AlternativeDescription) ? MenuData.UiAction.Description : MenuData.UiAction.AlternativeDescription);
try
{
MenuItemBorder.MouseLeftButtonUp -= MenuItemBorder_Click;
MenuItemBorder.TouchDown -= MenuItemBorder_Click;
}
catch { }
break;
case Enums.enumActionDisplayType.enabled:
MenuItemContent.ClearValue(OpacityProperty);
MenuItemBorder.ClearValue(IsHitTestVisibleProperty);
break;
}
MenuItemBorder.ToolTip = !string.IsNullOrEmpty(MenuData.UiAction?.Description) ? MenuData.UiAction?.Description : null;
ToolTip = !string.IsNullOrEmpty(MenuData.UiAction?.Description) ? MenuData.UiAction?.Description : null;
CustomTextBlock.Text = MenuData.MenuText;
CustomTextBlockBottom.Text = MenuData.MenuText;
if (string.IsNullOrWhiteSpace(MenuData.TrailingText))
{
CustomTrailingTextBlock.Text = string.Empty;
CustomTrailingTextBlock.Visibility = Visibility.Collapsed;
}
else
{
CustomTrailingTextBlock.Text = MenuData.TrailingText;
CustomTrailingTextBlock.Visibility = Visibility.Visible;
}
DrawEnhancedMenuInformation();
}
private void DrawEnhancedMenuInformation()
{
try
{
if (MenuData is cMenuDataContainer containerMenuData)
DrawContainer(containerMenuData);
else if (MenuData is cMenuDataSearchRelation searchRelationMenuData)
DrawSearchRelation(searchRelationMenuData);
else if (MenuData is cMenuDataLoading)
LoadingIcon.Visibility = Visibility.Visible;
else
DrawDefault();
}
catch (Exception E)
{
LogException(E);
}
void DrawContainer(cMenuDataContainer containerMenuData)
{
SubMenuCounterBorder.Visibility = Visibility.Visible;
var count = 0;
foreach (var entry in containerMenuData.SubMenuData)
{
if (entry.UiAction?.DisplayType == null || entry.UiAction?.DisplayType == Enums.enumActionDisplayType.enabled)
count++;
}
if (count == 0)
SubMenuCounterTextBlock.Text = "-";
else
SubMenuCounterTextBlock.Text = count.ToString();
}
void DrawSearchRelation(cMenuDataSearchRelation searchRelationMenuData)
{
if (!(searchRelationMenuData.Data is cF4sdApiSearchResultRelation relationData))
return;
if (searchRelationMenuData.IsMatchingRelation)
{
LoadingIcon.SelectedMaterialIcon = MaterialIconType.ic_link;
LoadingIcon.ClearValue(StyleProperty);
LoadingIcon.Visibility = Visibility.Visible;
}
if (relationData.Type is enumF4sdSearchResultClass.Ticket)
{
if (relationData.Infos is null)
return;
if (relationData.Infos.TryGetValue("Summary", out var ticketSummary))
{
CustomTextBlockBottom.Text = ticketSummary;
CustomTextBlockBorderBottom.Visibility = Visibility.Visible;
}
if (relationData.Infos.TryGetValue("StatusId", out var ticketStatusId))
{
Enum.TryParse(ticketStatusId, true, out enumTicketStatus ticketStatus);
switch (ticketStatus)
{
case enumTicketStatus.Unknown:
break;
case enumTicketStatus.New:
case enumTicketStatus.InProgress:
case enumTicketStatus.OnHold:
MenuItemIcon.SelectedMaterialIcon = MaterialIconType.ic_drafts;
break;
case enumTicketStatus.Closed:
MenuItemIcon.SelectedMaterialIcon = MaterialIconType.ic_mail;
break;
default:
break;
}
}
}
else
{
SearchRelationGrid.Visibility = Visibility.Visible;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using FasdDesktopUi.Basics.Converter;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using MaterialIcons;
using F4SD_AdaptableIcon;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class CustomMenuItem : UserControl
{
#region Properties
#region MenuData
private cMenuDataBase _menuData = new cMenuDataBase();
private readonly bool _isLean;
public cMenuDataBase MenuData
{
get { return _menuData; }
set
{
if (_menuData != value)
{
_menuData = value;
MenuDataChanged();
}
}
}
private void setIcon(AdaptableIcon.AdaptableIcon icon, IconData data)
{
var _visibilty = Visibility.Visible;
if (data.Intern != null)
icon.SelectedInternIcon = data.Intern;
else if (data.Material != null)
icon.SelectedMaterialIcon = data.Material;
else
_visibilty = Visibility.Hidden;
icon.IconHeight = MenuData.MenuIconSize * icon.IconHeight;
icon.IconWidth = MenuData.MenuIconSize * icon.IconWidth;
icon.Visibility = _visibilty;
}
private void MenuDataChanged()
{
setIcon(MenuItemIcon, MenuData.MenuIcon?.Icon ?? new IconData());
if (MenuData.MenuIcon?.Overlay != null)
setIcon(MenuItemOverlayIcon, (IconData)MenuData.MenuIcon.Overlay);
else
MenuItemOverlayIcon.Visibility = Visibility.Collapsed;
if (MenuData.MenuIcon?.IsInactive == true)
{
MenuItemIcon.Opacity = 0.7;
MenuItemOverlayIcon.Opacity = 0.7;
}
else
{
MenuItemIcon.Opacity = 1.0;
MenuItemOverlayIcon.Opacity = 1.0;
}
if (MenuData.MenuIcon?.Description != null)
{
MenuItemIcon.ToolTip = new CustomMenuItemToolTipTemplate(MenuData.MenuIcon.Description);
ToolTipService.SetInitialShowDelay(MenuItemIcon, 300);
ToolTipService.SetBetweenShowDelay(MenuItemIcon, 600);
ToolTipService.SetPlacement(MenuItemIcon, System.Windows.Controls.Primitives.PlacementMode.Top);
ToolTipService.SetHorizontalOffset(MenuItemIcon, 20);
ToolTipService.SetVerticalOffset(MenuItemIcon, 20);
}
string toolTip = MenuData.UiAction?.Description;
switch (MenuData.UiAction?.DisplayType)
{
case Enums.enumActionDisplayType.hidden:
//todo: add hidden state
break;
case Enums.enumActionDisplayType.disabled:
MenuItemContent.SetValue(OpacityProperty, 0.5);
MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory.NoHover");
if (!string.IsNullOrWhiteSpace(MenuData.UiAction.AlternativeDescription))
toolTip = MenuData.UiAction.AlternativeDescription;
try
{
MenuItemBorder.MouseLeftButtonUp -= MenuItemBorder_Click;
MenuItemBorder.TouchDown -= MenuItemBorder_Click;
}
catch { }
break;
case Enums.enumActionDisplayType.enabled:
MenuItemContent.ClearValue(OpacityProperty);
MenuItemBorder.ClearValue(IsHitTestVisibleProperty);
break;
}
if (!string.IsNullOrWhiteSpace(toolTip))
MenuItemBorder.ToolTip = toolTip;
CustomTextBlock.Text = MenuData.MenuText;
CustomTextBlockBottom.Text = MenuData.MenuText;
if (string.IsNullOrWhiteSpace(MenuData.TrailingText))
{
CustomTrailingTextBlock.Text = string.Empty;
CustomTrailingTextBlock.Visibility = Visibility.Collapsed;
}
else
{
CustomTrailingTextBlock.Text = MenuData.TrailingText;
CustomTrailingTextBlock.Visibility = Visibility.Visible;
}
DrawEnhancedMenuInformation();
}
private void DrawEnhancedMenuInformation()
{
try
{
if (MenuData is cMenuDataContainer containerMenuData)
DrawContainer(containerMenuData);
else if (MenuData is cMenuDataSearchRelation searchRelationMenuData)
DrawSearchRelation(searchRelationMenuData);
else if (MenuData is cMenuDataLoading)
LoadingIcon.Visibility = Visibility.Visible;
else
DrawDefault();
}
catch (Exception E)
{
LogException(E);
}
void DrawContainer(cMenuDataContainer containerMenuData)
{
SubMenuCounterBorder.Visibility = Visibility.Visible;
var count = 0;
foreach (var entry in containerMenuData.SubMenuData)
{
if (entry.UiAction?.DisplayType == null || entry.UiAction?.DisplayType == Enums.enumActionDisplayType.enabled)
count++;
}
if (count == 0)
SubMenuCounterTextBlock.Text = "-";
else
SubMenuCounterTextBlock.Text = count.ToString();
}
void DrawSearchRelation(cMenuDataSearchRelation searchRelationMenuData)
{
if (!(searchRelationMenuData.Data is cF4sdApiSearchResultRelation relationData))
return;
if (searchRelationMenuData.IsMatchingRelation)
{
LoadingIcon.SelectedMaterialIcon = MaterialIconType.ic_link;
LoadingIcon.ClearValue(StyleProperty);
LoadingIcon.Visibility = Visibility.Visible;
}
if (relationData.Type is enumF4sdSearchResultClass.Ticket)
{
if (relationData.Infos is null)
return;
if (relationData.Infos.TryGetValue("Summary", out var ticketSummary))
{
CustomTextBlockBottom.Text = ticketSummary;
CustomTextBlockBorderBottom.Visibility = Visibility.Visible;
}
}
else
{
SearchRelationGrid.Visibility = Visibility.Visible;
if (searchRelationMenuData.LastUsed == DateTime.MinValue)
{
LessThanTextBlock.Text= string.Empty;
LessThanTextBlock.Text = string.Empty;
LessThanTextBlock.Visibility = Visibility.Collapsed;
LastSeenTextBox.Visibility = Visibility.Collapsed;
ActivityIndicator.Width = 0;
ActivityIndicator.Visibility = Visibility.Collapsed;
ActivityTextBlock.Visibility = Visibility.Collapsed;
}
LastSeenTextBox.Visibility = Visibility.Collapsed;
ActivityIndicator.Width = 0;
ActivityIndicator.Visibility = Visibility.Collapsed;
ActivityTextBlock.Visibility = Visibility.Collapsed;
}
else
{
{
var lastUsedTimeSpan = DateTime.UtcNow - searchRelationMenuData.LastUsed;
LanguageDefinitionsConverter valueConverter = new LanguageDefinitionsConverter();
string lastSeenText = null;
@@ -194,86 +215,97 @@ namespace FasdDesktopUi.Basics.UserControls
LessThanTextBlock.Text = lastSeenText;
LessThanTextBlock.Visibility = Visibility.Visible;
LastSeenTextBox.Visibility = Visibility.Visible;
ActivityIndicator.Width = Math.Max(ActivityIndicator.Width * relationData.UsingLevel, ActivityIndicator.Width * 0.1);
ActivityIndicator.Visibility = Visibility.Visible;
ActivityTextBlock.Visibility = Visibility.Visible;
}
}
}
void DrawDefault()
{
if (string.IsNullOrWhiteSpace(MenuData.SubMenuText))
return;
CustomTextBlockBottom.Text = MenuData.SubMenuText;
CustomTextBlockBorderBottom.Visibility = Visibility.Visible;
}
}
#endregion
#endregion
public CustomMenuItem(bool isLean)
{
_isLean = isLean;
InitializeComponent();
}
#region Events
private void MenuItemBorder_Click(object sender, InputEventArgs e)
{
if (MenuData.UiAction == null)
return;
cUiActionBase.RaiseEvent(MenuData.UiAction, this, this);
}
#region Hover
private void MenuItemBorder_MouseEnter(object sender, MouseEventArgs e)
{
cUtility.SetTickerTextAnimation(CustomTextBlock, CustomTextBlockBorder);
if (string.IsNullOrWhiteSpace(CustomTextBlockBottom.Text) is false)
cUtility.SetTickerTextAnimation(CustomTextBlockBottom, CustomTextBlockBorderBottom);
}
private void MenuItemBorder_MouseLeave(object sender, MouseEventArgs e)
{
CustomTextBlock.TextTrimming = TextTrimming.CharacterEllipsis;
CustomTextBlock.BeginAnimation(MarginProperty, null);
CustomTextBlockBorder.ClearValue(WidthProperty);
CustomTextBlockBorderBottom.ClearValue(WidthProperty);
if (string.IsNullOrWhiteSpace(CustomTextBlockBottom.Text) is false)
{
CustomTextBlockBottom.TextTrimming = TextTrimming.CharacterEllipsis;
CustomTextBlockBottom.BeginAnimation(MarginProperty, null);
}
}
#endregion
#endregion
public void ShowDetailHeadings(bool showDetails)
{
SearchRelationGrid.ColumnDefinitions[0].Width =
showDetails ? new GridLength(1, GridUnitType.Auto) : new GridLength(0);
}
private void CustomMenuItemUc_Initialized(object sender, EventArgs e)
{
if (_isLean)
MenuItemBorder.Height = 30;
}
}
}
LastSeenTextBox.Visibility = Visibility.Visible;
ActivityIndicator.Width = Math.Max(ActivityIndicator.Width * relationData.UsingLevel, ActivityIndicator.Width * 0.1);
ActivityIndicator.Visibility = Visibility.Visible;
ActivityTextBlock.Visibility = Visibility.Visible;
}
}
}
void DrawDefault()
{
if (string.IsNullOrWhiteSpace(MenuData.SubMenuText))
return;
CustomTextBlockBottom.Text = MenuData.SubMenuText;
CustomTextBlockBorderBottom.Visibility = Visibility.Visible;
}
}
#endregion
#endregion
public CustomMenuItem(bool isLean)
{
_isLean = isLean;
InitializeComponent();
}
#region Events
private void MenuItemBorder_Click(object sender, InputEventArgs e)
{
if (MenuData.UiAction == null)
return;
if (MenuData.UiAction is cSubMenuAction subMenuAction)
{
bool useTempData = subMenuAction.UseTempData;
if (useTempData)
{
QuickActionSelector.Instance.Search.IsEnabled = false;
}
}
cUiActionBase.RaiseEvent(MenuData.UiAction, this, this);
}
#region Hover
private void MenuItemBorder_MouseEnter(object sender, MouseEventArgs e)
{
cUtility.SetTickerTextAnimation(CustomTextBlock, CustomTextBlockBorder);
if (string.IsNullOrWhiteSpace(CustomTextBlockBottom.Text) is false)
cUtility.SetTickerTextAnimation(CustomTextBlockBottom, CustomTextBlockBorderBottom);
}
private void MenuItemBorder_MouseLeave(object sender, MouseEventArgs e)
{
CustomTextBlock.TextTrimming = TextTrimming.CharacterEllipsis;
CustomTextBlock.BeginAnimation(MarginProperty, null);
CustomTextBlockBorder.ClearValue(WidthProperty);
CustomTextBlockBorderBottom.ClearValue(WidthProperty);
if (string.IsNullOrWhiteSpace(CustomTextBlockBottom.Text) is false)
{
CustomTextBlockBottom.TextTrimming = TextTrimming.CharacterEllipsis;
CustomTextBlockBottom.BeginAnimation(MarginProperty, null);
}
}
#endregion
#endregion
public void ShowDetailHeadings(bool showDetails)
{
SearchRelationGrid.ColumnDefinitions[0].Width =
showDetails ? new GridLength(1, GridUnitType.Auto) : new GridLength(0);
}
private void CustomMenuItemUc_Initialized(object sender, EventArgs e)
{
if (_isLean)
MenuItemBorder.Height = 30;
}
}
}

View File

@@ -0,0 +1,23 @@
<ToolTip x:Class="FasdDesktopUi.Basics.UserControls.CustomMenuItemToolTipTemplate"
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"
>
<ToolTip.Template>
<ControlTemplate>
<Border BorderBrush="{DynamicResource FontColor.Menu.Categories}" BorderThickness="1" CornerRadius="5"
Background="{DynamicResource BackgroundColor.Menu.Categories}"
>
<TextBlock Text="{Binding Text, RelativeSource={RelativeSource AncestorType=ToolTip}}"
Foreground="{DynamicResource FontColor.Menu.Categories}"
TextWrapping="Wrap"
MaxWidth="300"
Margin="8,3,8,5"
/>
</Border>
</ControlTemplate>
</ToolTip.Template>
</ToolTip>

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class CustomMenuItemToolTipTemplate : ToolTip
{
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(CustomMenuItemToolTipTemplate), new PropertyMetadata("This is a default popup text."));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public CustomMenuItemToolTipTemplate(string content = null)
{
InitializeComponent();
Text = content;
}
}
}

View File

@@ -26,8 +26,8 @@
Style="{DynamicResource SettingsPage.Close.Icon}"
BorderPadding="5"
SelectedMaterialIcon="ic_remove"
MouseLeftButtonUp="CollapseButton_MouseLeftButtonUp"
TouchDown="CollapseButton_TouchDown" />
MouseLeftButtonUp="CollapseButton_Click"
TouchDown="CollapseButton_Click" />
<TextBlock Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickAction.Parameter}" />

View File

@@ -1,23 +1,12 @@
using C4IT.FASD.Base;
using C4IT.Logging;
using FasdDesktopUi.Basics.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
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.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
@@ -104,13 +93,13 @@ namespace FasdDesktopUi.Basics.UserControls
switch (parameterValue)
{
case cAdjustableParameterBoolean booleanParameter:
AddBooleanParameter(parameter.Key, booleanParameter);
AddBooleanParameter(booleanParameter);
break;
case cAdjustableParameterNumerical numericalParameter:
AddNumericalParameter(parameter.Key, numericalParameter);
AddNumericalParameter(numericalParameter);
break;
case cAdjustableParameterDropDown dropDownParameter:
AddDropDownParameter(parameter.Key, dropDownParameter);
AddDropDownParameter(dropDownParameter);
break;
default:
break;
@@ -140,7 +129,7 @@ namespace FasdDesktopUi.Basics.UserControls
#region Helper
private void AddBooleanParameter(string parameterKey, cAdjustableParameterBoolean booleanParameter)
private void AddBooleanParameter(cAdjustableParameterBoolean booleanParameter)
{
try
{
@@ -157,7 +146,7 @@ namespace FasdDesktopUi.Basics.UserControls
outerPanel.Children.Add(valueCheckBox);
TextBlock parameterNameTextBlock = new TextBlock() { Text = booleanParameter.Names.GetValue(), Margin = new Thickness(0, 0, 7.5, 0) };
if(!string.IsNullOrEmpty(booleanParameter.Descriptions.GetValue()))
if (!string.IsNullOrEmpty(booleanParameter.Descriptions.GetValue()))
{
parameterNameTextBlock.ToolTip = booleanParameter.Descriptions.GetValue();
}
@@ -172,7 +161,7 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
private void AddNumericalParameter(string parameterKey, cAdjustableParameterNumerical numericalParameter)
private void AddNumericalParameter(cAdjustableParameterNumerical numericalParameter)
{
try
{
@@ -185,20 +174,11 @@ namespace FasdDesktopUi.Basics.UserControls
valueTextBox.SetResourceReference(BackgroundProperty, "BackgroundColor.DetailsPage.DataHistory.TitleColumn");
valueTextBox.SetResourceReference(BorderBrushProperty, "BackgroundColor.DetailsPage.DataHistory.ValueColumn");
valueTextBox.PreviewKeyDown += ((sender, e) =>
valueTextBox.TextChanged += (sender, e) =>
{
if (double.TryParse(valueTextBox.Text, out var parsedValue))
ParameterValues[numericalParameter] = parsedValue;
});
valueTextBox.PreviewTextInput += new TextCompositionEventHandler((sender, e) =>
{
var plannedValue = valueTextBox.Text.Insert(valueTextBox.CaretIndex, e.Text);
if (double.TryParse(plannedValue, out var parsedValue))
ParameterValues[numericalParameter] = parsedValue;
else
e.Handled = true;
});
};
DockPanel.SetDock(valueTextBox, Dock.Right);
outerPanel.Children.Add(valueTextBox);
@@ -219,7 +199,7 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
private void AddDropDownParameter(string parameterKey, cAdjustableParameterDropDown dropDownParameter)
private void AddDropDownParameter(cAdjustableParameterDropDown dropDownParameter)
{
try
{
@@ -227,8 +207,12 @@ namespace FasdDesktopUi.Basics.UserControls
ParameterValues[dropDownParameter] = dropDownParameter.Default;
ComboBox valueComboBox = new ComboBox() { SelectedItem = dropDownParameter.Default, MinWidth = 125 };
valueComboBox.Style = (Style)FindResource("DarkComboBox");
ComboBox valueComboBox = new ComboBox
{
SelectedItem = dropDownParameter.Default,
MinWidth = 125,
Style = (Style)FindResource("DarkComboBox")
};
valueComboBox.DropDownOpened += (sender, e) => cFocusInvoker.InvokeGotFocus(this, e);
valueComboBox.DropDownClosed += (sender, e) => cFocusInvoker.InvokeLostFocus(this, e);
@@ -346,9 +330,7 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
#region CollapseButton_Click
private void CollapseButton_Click()
private void CollapseButton_Click(object sender, InputEventArgs e)
{
try
{
@@ -360,17 +342,5 @@ namespace FasdDesktopUi.Basics.UserControls
LogException(E);
}
}
private void CollapseButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
CollapseButton_Click();
}
private void CollapseButton_TouchDown(object sender, TouchEventArgs e)
{
CollapseButton_Click();
}
#endregion
}
}

View File

@@ -23,12 +23,12 @@
Visibility="{Binding ElementName=DataCanvasUc, Path=IsDetailedLayout, Converter={StaticResource BoolToVisibility}}"
IsCloseButtonVisible="{Binding ElementName=DataCanvasUc, Path=DataCanvasData, Converter={StaticResource IsCloseButtonVisible}, ConverterParameter={x:Static converter:enumDataCanvasTypes.detailedData} }" />
<local:DynamicChart x:Name="DynamicChartUc"
HorizontalAlignment="Stretch"
<local:DynamicChart x:Name="DynamicChartUc"
HorizontalAlignment="Stretch"
Width="385"
Visibility="{Binding ElementName=DataCanvasUc, Path=IsDetailedLayout, Converter={StaticResource BoolToVisibility}}"
IsCloseButtonVisible="{Binding ElementName=DataCanvasUc, Path=DataCanvasData, Converter={StaticResource IsCloseButtonVisible}, ConverterParameter={x:Static converter:enumDataCanvasTypes.detailedData} }" />
<local:DetailedRecommendation x:Name="RecommendationUc"
Width="{Binding ElementName=DetailedDataUc, Path=ActualWidth, UpdateSourceTrigger=PropertyChanged}"
MinWidth="300"

View File

@@ -1,22 +1,9 @@
using C4IT.Logging;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Pages.DetailsPage.Models;
using FasdDesktopUi.Basics.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
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
@@ -63,7 +50,9 @@ namespace FasdDesktopUi.Basics.UserControls
_me.dataProvider.HealthCardDataHelper.LoadingHelper.DataRefreshed += _me.HealthCardDataHelper_DataRefreshed;
}
_me.QuickActionStatusUc.CancelQuickAction();
bool isSameQuickAction = oldData?.QuickActionStatusMonitorData?.QuickActionDefinition?.Id == newData?.QuickActionStatusMonitorData?.QuickActionDefinition?.Id;
if (!isSameQuickAction && newData?.QuickActionStatusMonitorData?.QuickActionDefinition?.RunImmediate != true)
_me.QuickActionStatusUc.CancelQuickAction();
_me.RecommendationUc.RecommendationData = _me.DataCanvasData.RecommendationData;
_me.RecommendationUc.CloseButtonClickedAction = _me.CloseDataCanvas;

View File

@@ -2,21 +2,10 @@
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Pages.DetailsPage.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace FasdDesktopUi.Basics.UserControls
{
@@ -27,7 +16,18 @@ namespace FasdDesktopUi.Basics.UserControls
#region RecommendationData
public static readonly DependencyProperty RecommendationDataProperty =
DependencyProperty.Register("RecommendationData", typeof(cRecommendationDataModel), typeof(DetailedRecommendation), new PropertyMetadata(new cRecommendationDataModel()));
DependencyProperty.Register("RecommendationData", typeof(cRecommendationDataModel), typeof(DetailedRecommendation), new PropertyMetadata(new cRecommendationDataModel(), new PropertyChangedCallback(HandleRecommendationDataChanged)));
private static void HandleRecommendationDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is DetailedRecommendation recommendationUc))
return;
if (string.IsNullOrWhiteSpace(recommendationUc.RecommendationData?.Recommendation))
recommendationUc.Visibility = Visibility.Collapsed;
else
recommendationUc.Visibility = Visibility.Visible;
}
public cRecommendationDataModel RecommendationData
{
@@ -66,7 +66,7 @@ namespace FasdDesktopUi.Basics.UserControls
if (d is DetailedRecommendation recommendation && e.NewValue is IconData iconData)
{
IconHelper.SetIconValue(recommendation.RecommendationIcon, iconData);
}
}
}
public string PrimaryIconColorResourceName
@@ -99,8 +99,7 @@ namespace FasdDesktopUi.Basics.UserControls
private void CloseButton_Click()
{
if (CloseButtonClickedAction != null)
CloseButtonClickedAction.Invoke();
CloseButtonClickedAction?.Invoke();
}
private void CloseButton_MouseUp(object sender, MouseButtonEventArgs e)

View File

@@ -3,6 +3,7 @@ using C4IT.F4SD.SupportCaseProtocoll.Models;
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using F4SD_AdaptableIcon.Enums;
using F4SD.Gamification;
using FasdDesktopUi.Basics.Converter;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.ProtocollService;
@@ -21,6 +22,7 @@ using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using static C4IT.Logging.cLogManager;
using F4SD.Gamification.Services;
namespace FasdDesktopUi.Basics.UserControls
{
@@ -30,6 +32,16 @@ namespace FasdDesktopUi.Basics.UserControls
private bool secretsAreShown = false;
private readonly IRawValueFormatter _rawValueFormatter = new RawValueFormatter();
private static object _currentQuickActionLock = new object();
private Guid _currentRunningQuickActionId;
public Guid CurrentRunningQuickActionId
{
get { lock (_currentQuickActionLock) { return _currentRunningQuickActionId; } }
set { lock (_currentQuickActionLock) { _currentRunningQuickActionId = value; } }
}
#region Helperclasses QuickAction Output
public abstract class cQuickActionOutput
@@ -38,7 +50,7 @@ namespace FasdDesktopUi.Basics.UserControls
public cQuickActionOutput(cF4sdQuickActionRevision.cOutput scriptOutput)
{
_rawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
_rawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
_rawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
ErrorCode = scriptOutput.ErrorCode;
ErrorDescription = scriptOutput.ErrorDescription;
@@ -804,7 +816,7 @@ namespace FasdDesktopUi.Basics.UserControls
if (measureValues?.Count <= 0)
return;
_rawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
_rawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
_rawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
for (int i = 0; i < measureValues.Count; i++)
@@ -1006,7 +1018,7 @@ namespace FasdDesktopUi.Basics.UserControls
else if (QuickActionData.ActionSteps.All(step => step.Status == enumQuickActionRevisionStatus.finishedSuccessfull))
status = enumQuickActionRevisionStatus.finishedSuccessfull;
RaiseEvent(new QuickActionEventArgs(QuickActionFinishedEvent, this) { QuickActionResult = result, QuickActionStatus = status, QuickAction = QuickActionData.QuickActionDefinition});
RaiseEvent(new QuickActionEventArgs(QuickActionFinishedEvent, this) { QuickActionResult = result, QuickActionStatus = status, QuickAction = QuickActionData.QuickActionDefinition });
CopyButton.Visibility = Visibility.Visible;
@@ -1022,6 +1034,7 @@ namespace FasdDesktopUi.Basics.UserControls
finally
{
VisualizeQuickActionFinish(status);
GamificationService.TrackAction(CockpitAction.QuickActionExecuted);
}
}

View File

@@ -0,0 +1,40 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.FooterButton"
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"
d:DesignHeight="35"
d:DesignWidth="230"
x:Name="FooterBtn">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<Grid x:Name="MainGrid"
x:FieldModifier="private"
Visibility="Collapsed">
<Border x:Name="MainBorder"
Style="{DynamicResource Menu.MainCategory}"
CornerRadius="7.5"
Height="35"
MouseLeftButtonUp="Button_Click"
TouchDown="Button_Click">
<StackPanel Orientation="Horizontal">
<ico:AdaptableIcon x:Name="ButtonIcon"
Margin="0 0 10 0" />
<TextBlock x:Name="ButtonLabel"
FontSize="16"
Text="{Binding ElementName=FooterBtn, Path=LabelText}" />
</StackPanel>
</Border>
<local:Badge Text="Beta"
Margin="-12.5"
HorizontalAlignment="Right"
VerticalAlignment="Top" />
</Grid>
</UserControl>

View File

@@ -0,0 +1,84 @@
using C4IT.MultiLanguage;
using F4SD_AdaptableIcon;
using FasdDesktopUi.Basics.Converter;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.UiActions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class FooterButton : UserControl
{
public string LabelText
{
get { return (string)GetValue(LabelTextProperty); }
set { SetValue(LabelTextProperty, value); }
}
public static readonly DependencyProperty LabelTextProperty =
DependencyProperty.Register(nameof(LabelText), typeof(string), typeof(FooterButton), new PropertyMetadata(string.Empty));
public cUiQuickAction QuickAction
{
get { return (cUiQuickAction)GetValue(QuickActionProperty); }
set { SetValue(QuickActionProperty, value); }
}
public static readonly DependencyProperty QuickActionProperty =
DependencyProperty.Register(nameof(QuickAction), typeof(cUiQuickAction), typeof(FooterButton), new PropertyMetadata(null, new PropertyChangedCallback(HandleQuickActionChanged)));
private static void HandleQuickActionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FooterButton button))
return;
button.UpdateButtonProperties();
}
private void UpdateButtonProperties()
{
MainGrid.Visibility = QuickAction is null ? Visibility.Collapsed : Visibility.Visible;
string tooltip = QuickAction != null ? null : cMultiLanguageSupport.GetItem("RemoteConnection.Button.Disabled");
SetEnableButton(QuickAction != null && QuickAction.DisplayType == Enums.enumActionDisplayType.enabled, tooltip);
IconData iconData = IconDataConverter.Convert(QuickAction.QuickActionConfig.Icon);
IconHelper.SetIconValue(ButtonIcon, iconData);
}
public FooterButton()
{
InitializeComponent();
}
private async void Button_Click(object sender, InputEventArgs e)
{
if (QuickAction is null)
return;
SetEnableButton(false);
cUiActionBase.RaiseEvent(QuickAction, this, this);
SetEnableButton(true);
}
internal void SetEnableButton(bool isEnabled, string tooltip = null)
{
if (isEnabled)
{
MainBorder.SetResourceReference(StyleProperty, "Menu.MainCategory");
MainBorder.ClearValue(OpacityProperty);
}
else
{
MainBorder.SetResourceReference(StyleProperty, "Menu.MainCategory.NoHover");
MainBorder.Opacity = 0.5;
}
MainBorder.ToolTip = tooltip;
}
}
}

View File

@@ -0,0 +1,74 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.Gamification.LevelTracker"
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.Gamification"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<UserControl.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.DetailsPage.DataHistory.TitleColumn.MainTitle}" />
</Style>
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<Grid Margin="10 0">
<Border BorderBrush="{DynamicResource Color.FunctionMarker}"
CornerRadius="50"
BorderThickness="6"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="#01010101"
Height="45"
Width="45">
</Border>
<TextBlock x:Name="LevelValueTextBlock"
TextAlignment="Center"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontWeight="Bold"
FontSize="20" />
<Ellipse x:Name="CoverEllipse"
Stroke="{DynamicResource Color.AppBackground}"
Opacity="0.5"
StrokeThickness="7"
Height="46"
Width="46"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<RotateTransform Angle="-90" />
</Ellipse.RenderTransform>
</Ellipse>
</Grid>
<StackPanel VerticalAlignment="Center">
<StackPanel.Resources>
<Style TargetType="StackPanel">
<Setter Property="Visibility"
Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=FrameworkElement}, Path=IsMouseOver}"
Value="True">
<Setter Property="Visibility"
Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<TextBlock x:Name="LevelTitelTextBlock"
FontWeight="Bold"
FontSize="18" />
<TextBlock x:Name="XpTextBlock"
FontWeight="Light"
FontSize="14" />
</StackPanel>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,39 @@
using F4SD.Gamification;
using F4SD.Gamification.Services;
using System;
using System.Windows.Controls;
using System.Windows.Media;
namespace FasdDesktopUi.Basics.UserControls.Gamification
{
public partial class LevelTracker : UserControl
{
public LevelTracker()
{
InitializeComponent();
}
private double GetCircumferenceOfCoverEllipse()
{
return (2 * Math.PI * (CoverEllipse.Height / 2.0 - CoverEllipse.StrokeThickness / 2.0)) / CoverEllipse.StrokeThickness;
}
protected override void OnInitialized(EventArgs e)
{
CoverEllipse.StrokeDashArray = new DoubleCollection() { GetCircumferenceOfCoverEllipse() };
LevelService.ExperiencePointsChanged += UpdateExperiencePoints;
base.OnInitialized(e);
}
private void UpdateExperiencePoints(object sender, LevelEventArgs e)
{
LevelValueTextBlock.Text = e.CurrentLevel.ToString();
double relativeProgress = (double)e.CurrentXp / (double)e.XpRequiredForLevelUp;
CoverEllipse.StrokeDashOffset = (GetCircumferenceOfCoverEllipse() * relativeProgress) * -1.0;
LevelTitelTextBlock.Text = e.LevelTitle;
XpTextBlock.Text = $"{e.CurrentXp} / {e.XpRequiredForLevelUp} XP";
}
}
}

View File

@@ -0,0 +1,72 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.InformationClassSearchBar"
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"
d:DesignHeight="450"
d:DesignWidth="800"
Name="_this"
IsVisibleChanged="BlurInvoker_IsActiveChanged">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<Border Background="{DynamicResource BackgroundColor.Menu.Categories}"
CornerRadius="17.5"
Margin="-2.5"
Padding="2.5"
VerticalAlignment="Bottom"
x:Name="BackgroundBorder"
x:FieldModifier="private">
<DockPanel>
<ico:AdaptableIcon x:Name="PhoneCallIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
Visibility="Collapsed"
SelectedMaterialIcon="ic_phone" />
<ico:AdaptableIcon x:Name="ComputerCallIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
Visibility="Collapsed"
SelectedInternIcon="misc_computer" />
<ico:AdaptableIcon x:Name="UserCallIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
Visibility="Collapsed"
SelectedInternIcon="misc_user" />
<ico:AdaptableIcon x:Name="WarningIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
PrimaryIconColor="{DynamicResource HighlightColor.Orange}"
Visibility="Collapsed"
SelectedInternIcon="status_bad" />
<local:SearchBar x:Name="InnerSearchBar"
x:FieldModifier="private"
SearchButtonSize="{Binding SearchButtonSize, ElementName=_this}"
CloseButtonSize="{Binding CloseButtonSize, ElementName=_this}"
PlaceholderText="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Searchbar.Placeholder.UserName}"
ShowCloseButton="True"
ShowSearchButton="True"
SearchValueChanged="InnerSearchBar_SearchValueChanged"
CancelledSearch="InnerSearchBar_CancelledSearch" />
</DockPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,287 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using FasdDesktopUi.Basics.Models;
using C4IT.FASD.Cockpit.Communication;
using C4IT.Logging;
using static C4IT.Logging.cLogManager;
using C4IT.MultiLanguage;
using C4IT.FASD.Base;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class InformationClassSearchBar : UserControl, IBlurInvoker
{
#region Properties
public enum eSearchStatus { message, active, fixedResult }
public eSearchStatus SearchStatus { get; private set; } = eSearchStatus.message;
private static CancellationTokenSource _currentSearchTaskToken = null;
private static Guid? _currentSearchTaskId = null;
private static readonly object _currentSearchTaskLock = new object();
private readonly Dictionary<enumF4sdSearchResultClass, UIElement> _searchIcons = null;
public delegate Task ChangedSearchValueDelegate(cFilteredResults results);
public ChangedSearchValueDelegate ChangedSearchValue { get; set; } = null;
public Action CancledSearchAction { get; set; }
public bool BlurInvoker_IsActive => IsVisible;
public string SearchValue => InnerSearchBar.SearchValue;
#endregion
#region Dependency Properties
public static readonly DependencyProperty SearchButtonSizeProperty =
DependencyProperty.Register(nameof(SearchButtonSize), typeof(double), typeof(InformationClassSearchBar), new PropertyMetadata(30.0));
public double SearchButtonSize
{
get => (double)GetValue(SearchButtonSizeProperty);
set => SetValue(SearchButtonSizeProperty, value);
}
public static readonly DependencyProperty CloseButtonSizeProperty =
DependencyProperty.Register(nameof(CloseButtonSize), typeof(double), typeof(InformationClassSearchBar), new PropertyMetadata(30.0));
public double CloseButtonSize
{
get => (double)GetValue(CloseButtonSizeProperty);
set => SetValue(CloseButtonSizeProperty, value);
}
#endregion
public InformationClassSearchBar()
{
InitializeComponent();
_searchIcons = new Dictionary<enumF4sdSearchResultClass, UIElement>
{
{ enumF4sdSearchResultClass.Phone, PhoneCallIndicator },
{ enumF4sdSearchResultClass.User, UserCallIndicator },
{ enumF4sdSearchResultClass.Computer, ComputerCallIndicator }
};
}
public void BlurInvoker_IsActiveChanged(object sender, DependencyPropertyChangedEventArgs e)
{
BlurInvoker.InvokeVisibilityChanged(this, new EventArgs());
if (e.NewValue is bool newVisible)
{
if (!newVisible)
{
InnerSearchBar.IsInputEnabled = true;
InnerSearchBar.ShowSearchButton = true;
WarningIndicator.Visibility = Visibility.Collapsed;
TicketOverview.Instance?.ResetSelection();
foreach (var entry in _searchIcons.Values)
entry.Visibility = Visibility.Collapsed;
}
SetApiStatus();
}
if (Visibility == Visibility.Visible)
Dispatcher.BeginInvoke((Action)(() => InnerSearchBar.FocusInput()), DispatcherPriority.Render);
}
public void Clear()
{
SearchStatus = eSearchStatus.message;
InnerSearchBar.Clear();
}
public void ActivateManualSearch()
{
SearchStatus = eSearchStatus.active;
InnerSearchBar.ShowSearchButton = true;
WarningIndicator.Visibility = Visibility.Collapsed;
foreach (var entry in _searchIcons.Values)
entry.Visibility = Visibility.Collapsed;
InnerSearchBar.Clear();
InnerSearchBar.IsInputEnabled = true;
InnerSearchBar.FocusInput();
}
public void SetSearchText(string search)
{
SearchStatus = eSearchStatus.active;
InnerSearchBar.SetSearchText(search);
}
public void SetSpinnerVisibility(Visibility visibility)
{
InnerSearchBar.SetSpinnerVisibility(visibility);
}
public async Task SetFixedSearchResultAsync(enumF4sdSearchResultClass resultClass, string search, cFilteredResults result)
{
SearchStatus = eSearchStatus.fixedResult;
InnerSearchBar.IsInputEnabled = false;
InnerSearchBar.ShowSearchButton = false;
WarningIndicator.Visibility = Visibility.Collapsed;
foreach (var entryIcon in _searchIcons)
entryIcon.Value.Visibility = entryIcon.Key == resultClass ? Visibility.Visible : Visibility.Collapsed;
InnerSearchBar.SetSearchText(search);
if (ChangedSearchValue != null)
await ChangedSearchValue.Invoke(result);
}
public void SetApiStatus()
{
try
{
var status = cConnectionStatusHelper.Instance?.ApiConnectionStatus;
if (status == null)
return;
bool isEnabled = false;
string txt = null;
switch (status)
{
case cConnectionStatusHelper.enumOnlineStatus.online:
isEnabled = true;
break;
case cConnectionStatusHelper.enumOnlineStatus.connectionError:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ConnectError");
break;
case cConnectionStatusHelper.enumOnlineStatus.incompatibleServerVersion:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.IncompatibleVersion");
break;
case cConnectionStatusHelper.enumOnlineStatus.serverStarting:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ServerStarting");
break;
case cConnectionStatusHelper.enumOnlineStatus.serverNotConfigured:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ServerNotConfigured");
break;
case cConnectionStatusHelper.enumOnlineStatus.illegalConfig:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.IllegalConfig");
break;
case cConnectionStatusHelper.enumOnlineStatus.unauthorized:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.Unauthorized");
break;
default:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.Offline");
break;
}
if (!isEnabled)
{
SearchStatus = eSearchStatus.message;
InnerSearchBar.SetSearchText(txt);
InnerSearchBar.IsInputEnabled = false;
WarningIndicator.Visibility = Visibility.Visible;
InnerSearchBar.ShowSearchButton = false;
foreach (var entry in _searchIcons.Values)
entry.Visibility = Visibility.Collapsed;
}
}
catch (Exception e)
{
LogException(e);
}
}
private async Task CancelRunningSearchTaskAsync()
{
lock (_currentSearchTaskLock)
{
if (_currentSearchTaskToken != null)
{
LogEntry("Canceling current running search...");
_currentSearchTaskToken.Cancel(true);
_currentSearchTaskToken = null;
}
}
Guid? currentTaskId = null;
lock (_currentSearchTaskLock)
{
if (_currentSearchTaskId != null)
{
currentTaskId = _currentSearchTaskId;
_currentSearchTaskId = null;
}
}
if (currentTaskId != null)
{
LogEntry("Sending a search stop...");
await cFasdCockpitCommunicationBase.Instance.GetSearchResultsStop((Guid)currentTaskId, CancellationToken.None);
}
}
private async void InnerSearchBar_SearchValueChanged(object sender, string searchValue)
{
MethodBase cm = null;
if (cLogManager.DefaultLogger.IsDebug) { cm = MethodBase.GetCurrentMethod(); LogMethodBegin(cm); }
try
{
await CancelRunningSearchTaskAsync();
lock (_currentSearchTaskLock)
{
LogEntry("Start running new search...");
SearchValueChanged?.Invoke(this, searchValue);
}
}
catch (Exception e)
{
LogException(e);
}
finally
{
if (cm != null) LogMethodEnd(cm);
}
}
private void InnerSearchBar_CancelledSearch(object sender, RoutedEventArgs e)
{
e.Handled = true;
RaiseCancledSearchEvent();
if (cConnectionStatusHelper.Instance?.ApiConnectionStatus == cConnectionStatusHelper.enumOnlineStatus.online)
InnerSearchBar.Clear();
CancledSearchAction?.Invoke();
}
#region Events
public event EventHandler<string> SearchValueChanged;
public static readonly RoutedEvent CancledSearchEvent =
EventManager.RegisterRoutedEvent(nameof(CancledSearch), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(InformationClassSearchBar));
public event RoutedEventHandler CancledSearch
{
add => AddHandler(CancledSearchEvent, value);
remove => RemoveHandler(CancledSearchEvent, value);
}
private void RaiseCancledSearchEvent()
{
RaiseEvent(new RoutedEventArgs(CancledSearchEvent));
}
#endregion
}
}

View File

@@ -1,22 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Linq;
using System.Threading.Tasks;
using C4IT.FASD.Base;
using F4SD_AdaptableIcon;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.SupportCase;
using FasdDesktopUi.Basics.Services.SupportCase.Controllers;
using FasdDesktopUi.Basics.UiActions;
using FasdDesktopUi.Pages;
using FasdDesktopUi.Pages.SearchPage;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using F4SD_AdaptableIcon;
namespace FasdDesktopUi.Basics.UserControls
{
@@ -26,6 +26,8 @@ namespace FasdDesktopUi.Basics.UserControls
#region PopUpIsVisible
public SupportCaseController SupportCaseController { get; set; }
internal static readonly DependencyPropertyKey PopUpIsVisibleKey = DependencyProperty.RegisterReadOnly("PopUpIsVisible", typeof(bool), typeof(MenuBar), new PropertyMetadata(false));
public static readonly DependencyProperty PopUpIsVisibleProperty = PopUpIsVisibleKey.DependencyProperty;
@@ -109,7 +111,7 @@ namespace FasdDesktopUi.Basics.UserControls
{
AdaptableIcon.AdaptableIcon menuIcon = new AdaptableIcon.AdaptableIcon() { Style = menuPinnedIconStyle };
IconData icon = sortedMenuData[i].MenuIcon;
IconData icon = sortedMenuData[i].MenuIcon.Icon;
if (icon.Intern != null)
menuIcon.SelectedInternIcon = icon.Intern;
else if(icon.Material != null)
@@ -142,17 +144,23 @@ namespace FasdDesktopUi.Basics.UserControls
if (sortedMenuData[i].IconPositionIndex >= 0)
MenuBarStackPanel.Children.Insert(MenuBarStackPanel.Children.Count - 1, menuIcon);
}
if (cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate != null)
cCopyTemplate defaultCopyTemplate = null;
defaultCopyTemplate = SupportCaseController?.GetCopyTemplate();
if (defaultCopyTemplate != null)
{
var copyIcon = new AdaptableIcon.AdaptableIcon()
{
Style = menuPinnedIconStyle,
SelectedInternIcon = enumInternIcons.menuBar_copy,
ToolTip = cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate.Descriptions.GetValue(Default: null),
ToolTip = defaultCopyTemplate?.Descriptions.GetValue(Default: null),
};
copyIcon.Tag = new cMenuDataBase() { IconPositionIndex = 2, MenuIcon = new F4SD_AdaptableIcon.IconData(enumInternIcons.menuBar_copy), UiAction = new cUiCopyAction(cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate) };
copyIcon.Tag = new cMenuDataBase() { IconPositionIndex = 2, MenuIcon = new cMenuDataBase.MenuIconInfo(new F4SD_AdaptableIcon.IconData(enumInternIcons.menuBar_copy)), UiAction = new cUiCopyAction(defaultCopyTemplate) };
copyIcon.MouseLeftButtonUp += MenuItem_MouseUp;
copyIcon.TouchDown += MenuItem_TouchDown;

View File

@@ -167,6 +167,7 @@
TextChanged="NotepadRichTextBox_TextChanged"
Foreground="{DynamicResource FontColor.DetailsPage.Widget}"
Background="{DynamicResource BackgroundColor.DetailsPage.Widget.Title}"
SpellCheck.IsEnabled="True"
SelectionChanged="NotepadRichTextBox_SelectionChanged"
IsVisibleChanged="NotepadRichTextBox_IsVisibleChanged"
GotKeyboardFocus="NotepadRichTextBox_GotKeyboardFocus">

View File

@@ -1,4 +1,5 @@
using F4SD_AdaptableIcon.Enums;
using C4IT.FASD.Base;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Helper;
using System;
using System.IO;
@@ -8,6 +9,7 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Threading;
using static C4IT.Logging.cLogManager;
@@ -109,7 +111,7 @@ namespace FasdDesktopUi.Basics.UserControls
}
_me.LockNotepadIcon.SelectedInternIcon = _me.IsLocked ? F4SD_AdaptableIcon.Enums.enumInternIcons.lock_closed : F4SD_AdaptableIcon.Enums.enumInternIcons.lock_open;
_me.CloseNotepadIcon.IsEnabled = _me.IsLocked ? false : true;
}
@@ -147,9 +149,9 @@ namespace FasdDesktopUi.Basics.UserControls
{
return;
}
}
catch(Exception E)
catch (Exception E)
{
LogException(E);
}
@@ -172,8 +174,8 @@ namespace FasdDesktopUi.Basics.UserControls
#endregion
#region Methods
private void NotepadRichTextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
try
@@ -309,7 +311,11 @@ namespace FasdDesktopUi.Basics.UserControls
if (DataProvider is null)
return;
Dispatcher.Invoke(() => DataProvider.SaveCaseNotes());
Dispatcher.Invoke(() =>
{
SetLanguageOfDocument();
DataProvider.SaveCaseNotes();
});
}
catch (Exception E)
{
@@ -317,9 +323,19 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
private void SetLanguageOfDocument()
{
if (cF4SDCockpitXmlConfig.Instance.HealthCardConfig?.ProtocollLanguage != null)
{
var languageTag = XmlLanguage.GetLanguage(cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage);
TextRange range = new TextRange(NotepadRichTextBox.Document.ContentStart, NotepadRichTextBox.Document.ContentEnd);
range.ApplyPropertyValue(FrameworkElement.LanguageProperty, languageTag);
}
}
private void NotepadRichTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
saveTimer?.Stop();
saveTimer?.Start();
@@ -734,7 +750,7 @@ namespace FasdDesktopUi.Basics.UserControls
return;
}
NotepadVisibilityChanged?.Invoke(this, true);
}
catch (Exception E)
{

View File

@@ -15,6 +15,7 @@
<UserControl.Resources>
<converter:NullValueToVisibilityConverter x:Key="NullToVisibility" />
<converter:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<Border Padding="10"
@@ -37,7 +38,7 @@
Style="{DynamicResource Menu.Selector.Icon.Lock}"
MouseUp="LockButton_MouseUp"
TouchDown="LockButton_TouchDown"
MouseLeave="LockButton_MouseLeave"/>
MouseLeave="LockButton_MouseLeave" />
<ico:AdaptableIcon x:Name="BackButton"
DockPanel.Dock="Left"
@@ -74,9 +75,22 @@
</DockPanel>
<local:SearchBar x:Name="Search"
DockPanel.Dock="Top"
PlaceholderText="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Searchbar.Placeholder}"
ShowCloseButton="False"
SearchButtonSize="26"
DebounceInterval="0"
SearchBackground="{DynamicResource BackgroundColor.DetailsPage.Widget.Title}"
SearchValueChanged="SearchBar_SearchValueChanged"
Margin="0 0 0 10"
Focusable="True"
Height="26" />
<local:CustomMenu x:Name="SubMenuUc"
DockPanel.Dock="Top"
MenuDataList="{Binding ElementName=QuickActionSelectorUc, Path=QuickActionList}" />
MenuDataList="{Binding ElementName=QuickActionSelectorUc, Path=QuickActionList}"
Width="270"/>
</DockPanel>

View File

@@ -1,23 +1,13 @@
using System;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions;
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 C4IT.FASD.Base;
using C4IT.Logging;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Models;
using static C4IT.Logging.cLogManager;
using static FasdDesktopUi.Basics.UserControls.InformationClassSearchBar;
namespace FasdDesktopUi.Basics.UserControls
{
@@ -25,9 +15,12 @@ namespace FasdDesktopUi.Basics.UserControls
{
#region Properties
public event EventHandler<string> SearchValueChanged;
public Action CloseButtonClickedAction { get; set; }
public Action<bool> LockStatusChanged { get; set; }
public static QuickActionSelector Instance;
#region IsLocked DependencyProperty
public bool IsLocked
@@ -49,7 +42,7 @@ namespace FasdDesktopUi.Basics.UserControls
return;
}
_me.CloseButton.IsEnabled = _me.IsLocked ? false : true;
_me.CloseButton.IsEnabled = !_me.IsLocked;
}
catch (Exception E)
@@ -110,10 +103,13 @@ namespace FasdDesktopUi.Basics.UserControls
public QuickActionSelector()
{
InitializeComponent();
Search.ActivateManualSearch();
Instance = this;
}
public void BlurInvoker_IsActiveChanged(object sender, DependencyPropertyChangedEventArgs e)
{
Search.IsInputEnabled = this.Visibility == Visibility.Visible;
BlurInvoker.InvokeVisibilityChanged(this, new EventArgs());
}
@@ -178,7 +174,7 @@ namespace FasdDesktopUi.Basics.UserControls
#region CloseButton
private void CloseButton_Click()
public void CloseButton_Click()
{
try
{
@@ -187,9 +183,16 @@ namespace FasdDesktopUi.Basics.UserControls
QuickActionList = null;
Visibility = Visibility.Collapsed;
Search.IsEnabled = true;
if (CloseButtonClickedAction != null)
CloseButtonClickedAction.Invoke();
Window window = Window.GetWindow(this);
if (window != null)
{
FocusManager.SetFocusedElement(window, window);
Keyboard.Focus(window);
}
CloseButtonClickedAction?.Invoke();
}
catch (Exception E)
{
@@ -217,6 +220,8 @@ namespace FasdDesktopUi.Basics.UserControls
TempQuickActionSelectorHeading = null;
QuickActionList = TempQuickActionList;
TempQuickActionList = null;
Search.IsEnabled = true;
Search.FocusInput();
}
private void BackButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
@@ -230,5 +235,8 @@ namespace FasdDesktopUi.Basics.UserControls
}
#endregion
private void SearchBar_SearchValueChanged(object sender, string e)
=> SearchValueChanged?.Invoke(this, e);
}
}

View File

@@ -30,7 +30,6 @@ namespace FasdDesktopUi.Basics.UserControls.QuickTip
set { SetValue(QuickTipNameProperty, value); }
}
// Using a DependencyProperty as the backing store for QuickTipName. This enables animation, styling, binding, etc...
public static readonly DependencyProperty QuickTipNameProperty =
DependencyProperty.Register("QuickTipName", typeof(string), typeof(QuickTipStatusMonitor), new PropertyMetadata("Quick Tip Name"));
@@ -44,7 +43,6 @@ namespace FasdDesktopUi.Basics.UserControls.QuickTip
set { SetValue(QuickTipIconProperty, value); }
}
// Using a DependencyProperty as the backing store for QuickTipIcon. This enables animation, styling, binding, etc...
public static readonly DependencyProperty QuickTipIconProperty =
DependencyProperty.Register("QuickTipIcon", typeof(IconData), typeof(QuickTipStatusMonitor), new PropertyMetadata(new IconData(enumInternIcons.none)));
@@ -58,7 +56,6 @@ namespace FasdDesktopUi.Basics.UserControls.QuickTip
set { SetValue(QuickTipElementDataProperty, value); }
}
// Using a DependencyProperty as the backing store for QuickTipElementData. This enables animation, styling, binding, etc...
public static readonly DependencyProperty QuickTipElementDataProperty =
DependencyProperty.Register("QuickTipElementData", typeof(List<cUiQuickTipElement>), typeof(QuickTipStatusMonitor), new PropertyMetadata(new List<cUiQuickTipElement>(), HandleQuickTipElementDataChanged));
@@ -94,20 +91,6 @@ namespace FasdDesktopUi.Basics.UserControls.QuickTip
#endregion
#region HasFocusIndex
public int HasFocusIndex
{
get { return (int)GetValue(HasFocusIndexProperty); }
set { SetValue(HasFocusIndexProperty, value); }
}
// Using a DependencyProperty as the backing store for HasFocusIndex. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HasFocusIndexProperty =
DependencyProperty.Register("HasFocusIndex", typeof(int), typeof(QuickTipStatusMonitor), new PropertyMetadata(0));
#endregion
#endregion
public QuickTipStatusMonitor()
@@ -255,8 +238,14 @@ namespace FasdDesktopUi.Basics.UserControls.QuickTip
return;
bool wasSuccessfull = step.SuccessState == enumQuickActionSuccess.finished || step.SuccessState == enumQuickActionSuccess.successfull;
string currentLanguage = cMultiLanguageSupport.CurrentLanguage;
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage ?? currentLanguage;
ProtocollEntryBase protocollEntry = QuickTipStepProtocollEntryOutput.GetQuickTipStepProtocollEntry(step.StepData.QuickTipElementDefinition, wasSuccessfull);
cMultiLanguageSupport.CurrentLanguage = currentLanguage;
F4SDProtocoll.Instance.Add(protocollEntry);
}
catch (Exception ex)
@@ -331,26 +320,40 @@ namespace FasdDesktopUi.Basics.UserControls.QuickTip
QuickTipElementData = new List<cUiQuickTipElement>();
}
private void CancelButton_Click(object sender, InputEventArgs args) => CancelQuickTip();
private void CancelButton_Click(object sender, InputEventArgs args) => TryCancelQuickTip();
private void CancelQuickTip()
/// <returns>If QuickTip could be canceled</returns>
internal bool TryCancelQuickTip()
{
if (_stepList.Any(step => step.SuccessState != enumQuickActionSuccess.unknown))
if (CustomMessageBox.Show(cMultiLanguageSupport.GetItem("QuickTips.Dialog.Cancel"), "Quick Tip", enumHealthCardStateLevel.Warning, null, true) != true)
return;
return false;
Visibility = Visibility.Collapsed;
int finishedStepCount = _stepList.Count(step => step.SuccessState == enumQuickActionSuccess.finished);
AddQuickTipEndToProtocoll(QuickTipName, finishedStepCount, _stepList.Count, true);
QuickTipElementData = new List<cUiQuickTipElement>();
return true;
}
private void AddQuickTipEndToProtocoll(string quickTipName, int finishedStepCount, int totalStepCount, bool wasCanceled)
{
string ascii = wasCanceled ? cMultiLanguageSupport.GetItem("QuickTips.Copy.Cancel") : cMultiLanguageSupport.GetItem("QuickTips.Copy.Finish");
ascii = string.Format(ascii, quickTipName, finishedStepCount, totalStepCount);
F4SDProtocoll.Instance.Add(new TextualProtocollEntry(ascii, ascii));
string currentLanguage = cMultiLanguageSupport.CurrentLanguage;
try
{
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage ?? currentLanguage;
string ascii = wasCanceled ? cMultiLanguageSupport.GetItem("QuickTips.Copy.Cancel") : cMultiLanguageSupport.GetItem("QuickTips.Copy.Finish");
ascii = string.Format(ascii, quickTipName, finishedStepCount, totalStepCount);
F4SDProtocoll.Instance.Add(new TextualProtocollEntry(ascii, ascii));
}
finally
{
cMultiLanguageSupport.CurrentLanguage = currentLanguage;
}
}
private void QuickTipStatusMonitorUc_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
@@ -358,9 +361,21 @@ namespace FasdDesktopUi.Basics.UserControls.QuickTip
if (!IsVisible)
return;
string ascii = cMultiLanguageSupport.GetItem("QuickTips.Copy.Start");
ascii = string.Format(ascii, QuickTipName);
F4SDProtocoll.Instance.Add(new TextualProtocollEntry(ascii, ascii));
string currentLanguage = cMultiLanguageSupport.CurrentLanguage;
try
{
cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage ?? currentLanguage;
string ascii = cMultiLanguageSupport.GetItem("QuickTips.Copy.Start");
ascii = string.Format(ascii, QuickTipName);
F4SDProtocoll.Instance.Add(new TextualProtocollEntry(ascii, ascii));
}
finally
{
cMultiLanguageSupport.CurrentLanguage = currentLanguage;
}
}
}
}

View File

@@ -3,21 +3,19 @@
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"
d:DesignHeight="450"
d:DesignWidth="800"
Name="_this"
IsVisibleChanged="BlurInvoker_IsActiveChanged"
Name="Search"
Loaded="SearchBar_Loaded">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
</UserControl.Resources>
<Border Background="{DynamicResource BackgroundColor.Menu.Categories}"
<Border Background="{Binding ElementName=Search, Path=SearchBackground}"
CornerRadius="17.5"
Margin="-2.5"
Padding="2.5"
@@ -29,47 +27,15 @@
<ico:AdaptableIcon x:Name="SearchButton"
x:FieldModifier="private"
DockPanel.Dock="Left"
Visibility="{Binding ShowSearchButton, ElementName=Search, Converter={StaticResource BoolToVisibility}}"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
MouseUp="SearchButton_Click"
TouchDown="SearchButton_Click"
IconBackgroundColor="Transparent"
IconHeight="{Binding SearchButtonSize, RelativeSource={RelativeSource AncestorType=UserControl}}"
IconWidth="{Binding SearchButtonSize, RelativeSource={RelativeSource AncestorType=UserControl}}"
IconHeight="{Binding SearchButtonSize, ElementName=Search}"
IconWidth="{Binding SearchButtonSize, ElementName=Search}"
SelectedInternIcon="menuBar_search" />
<ico:AdaptableIcon x:Name="PhoneCallIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
Visibility="Collapsed"
SelectedMaterialIcon="ic_phone" />
<ico:AdaptableIcon x:Name="ComputerCallIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
Visibility="Collapsed"
SelectedInternIcon="misc_computer" />
<ico:AdaptableIcon x:Name="UserCallIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
Visibility="Collapsed"
SelectedInternIcon="misc_user" />
<ico:AdaptableIcon x:Name="WarningIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
PrimaryIconColor="#FFFF8800"
Visibility="Collapsed"
SelectedInternIcon="status_bad" />
<Grid DockPanel.Dock="Left">
<TextBlock IsHitTestVisible="False"
@@ -83,7 +49,7 @@
<DataTrigger Binding="{Binding Text, ElementName=SearchTextBox}"
Value="">
<Setter Property="Text"
Value="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Searchbar.Placeholder.UserName}" />
Value="{Binding PlaceholderText, ElementName=Search}" />
</DataTrigger>
</Style.Triggers>
</Style>
@@ -92,7 +58,8 @@
<TextBox x:Name="SearchTextBox"
x:FieldModifier="private"
Text="{Binding ElementName=_this, Path=SearchValue, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}"
IsEnabled="{Binding IsInputEnabled, ElementName=Search}"
Text="{Binding ElementName=Search, Path=SearchValue, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}"
Style="{DynamicResource SearchBar.TextBox}" />
<StackPanel Orientation="Horizontal"
@@ -114,11 +81,13 @@
</TransformGroup>
</ico:AdaptableIcon.RenderTransform>
</ico:AdaptableIcon>
<ico:AdaptableIcon x:Name="CloseButton"
x:FieldModifier="private"
Visibility="{Binding ShowCloseButton, ElementName=Search, Converter={StaticResource BoolToVisibility}}"
Style="{DynamicResource SettingsPage.Close.Icon}"
IconHeight="{Binding CloseButtonSize, RelativeSource={RelativeSource AncestorType=UserControl}}"
IconWidth="{Binding CloseButtonSize, RelativeSource={RelativeSource AncestorType=UserControl}}"
IconHeight="{Binding CloseButtonSize, ElementName=Search}"
IconWidth="{Binding CloseButtonSize, ElementName=Search}"
Margin="-3 0 0 0"
Padding="0"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Global.NavBar.Close}"

View File

@@ -1,38 +1,99 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using FasdDesktopUi.Basics.Models;
using C4IT.FASD.Cockpit.Communication;
using C4IT.Logging;
using static C4IT.Logging.cLogManager;
using C4IT.MultiLanguage;
using C4IT.FASD.Base;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class SearchBar : UserControl, IBlurInvoker
public partial class SearchBar : UserControl
{
private const int constTimeBetweenKeystrokes = 250;
#region Propeties
public enum eSearchStatus { message, active, fixedResult };
public eSearchStatus SearchStatus { get; private set; } = eSearchStatus.message;
#region Search Value Property
private readonly DispatcherTimer _searchTimer = new DispatcherTimer();
private static CancellationTokenSource _currentSearchTaskToken = null;
private static Guid? _currentSearchTaskId = null;
private static readonly object _currentSearchTaskLock = new object();
#region Dependency Properties
public static readonly DependencyProperty SearchButtonSizeProperty =
DependencyProperty.Register(nameof(SearchButtonSize), typeof(double), typeof(SearchBar), new PropertyMetadata(30.0));
public double SearchButtonSize
{
get => (double)GetValue(SearchButtonSizeProperty);
set => SetValue(SearchButtonSizeProperty, value);
}
public static readonly DependencyProperty CloseButtonSizeProperty =
DependencyProperty.Register(nameof(CloseButtonSize), typeof(double), typeof(SearchBar), new PropertyMetadata(30.0));
public double CloseButtonSize
{
get => (double)GetValue(CloseButtonSizeProperty);
set => SetValue(CloseButtonSizeProperty, value);
}
public static readonly DependencyProperty ShowCloseButtonProperty =
DependencyProperty.Register(nameof(ShowCloseButton), typeof(bool), typeof(SearchBar), new PropertyMetadata(true));
public bool ShowCloseButton
{
get => (bool)GetValue(ShowCloseButtonProperty);
set => SetValue(ShowCloseButtonProperty, value);
}
public static readonly DependencyProperty ShowSearchButtonProperty =
DependencyProperty.Register(nameof(ShowSearchButton), typeof(bool), typeof(SearchBar), new PropertyMetadata(true));
public bool ShowSearchButton
{
get => (bool)GetValue(ShowSearchButtonProperty);
set => SetValue(ShowSearchButtonProperty, value);
}
public static readonly DependencyProperty PlaceholderTextProperty =
DependencyProperty.Register(nameof(PlaceholderText), typeof(string), typeof(SearchBar), new PropertyMetadata(string.Empty));
public string PlaceholderText
{
get => (string)GetValue(PlaceholderTextProperty);
set => SetValue(PlaceholderTextProperty, value);
}
public static readonly DependencyProperty DebounceIntervalProperty =
DependencyProperty.Register(nameof(DebounceInterval), typeof(TimeSpan), typeof(SearchBar),
new PropertyMetadata(TimeSpan.FromMilliseconds(250), OnDebounceIntervalChanged));
public TimeSpan DebounceInterval
{
get => (TimeSpan)GetValue(DebounceIntervalProperty);
set => SetValue(DebounceIntervalProperty, value);
}
private static void OnDebounceIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((SearchBar)d)._searchTimer.Interval = (TimeSpan)e.NewValue;
}
public static readonly DependencyProperty IsInputEnabledProperty =
DependencyProperty.Register(nameof(IsInputEnabled), typeof(bool), typeof(SearchBar), new PropertyMetadata(true));
public bool IsInputEnabled
{
get => (bool)GetValue(IsInputEnabledProperty);
set => SetValue(IsInputEnabledProperty, value);
}
public SolidColorBrush SearchBackground
{
get { return (SolidColorBrush)GetValue(SearchBackgroundProperty); }
set { SetValue(SearchBackgroundProperty, value); }
}
public static readonly DependencyProperty SearchBackgroundProperty =
DependencyProperty.Register(nameof(SearchBackground), typeof(SolidColorBrush), typeof(SearchBar), new PropertyMetadata(null));
#endregion
#region SearchValue
private string _searchValue = null;
public string SearchValue
@@ -43,111 +104,49 @@ namespace FasdDesktopUi.Basics.UserControls
if (value != _searchValue)
{
_searchValue = value;
if (SearchStatus == eSearchStatus.active)
if (IsInputEnabled)
HandleSearchValueChanged();
}
}
}
private readonly Dictionary<enumF4sdSearchResultClass, UIElement> _searchIcons = null;
#endregion
#region Events
public event EventHandler<string> SearchValueChanged;
public delegate Task ChangedSearchValueDelegate(cFilteredResults results);
public static readonly RoutedEvent CancelledSearchEvent =
EventManager.RegisterRoutedEvent(nameof(CancelledSearch), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SearchBar));
public ChangedSearchValueDelegate ChangedSearchValue { get; set; } = null;
public Action CancledSearchAction { get; set; }
public bool BlurInvoker_IsActive => IsVisible;
#endregion
#region Dependency Propertys
public double SearchButtonSize
public event RoutedEventHandler CancelledSearch
{
get { return (double)GetValue(SearchButtonSizeProperty); }
set { SetValue(SearchButtonSizeProperty, value); }
add => AddHandler(CancelledSearchEvent, value);
remove => RemoveHandler(CancelledSearchEvent, value);
}
public static readonly DependencyProperty SearchButtonSizeProperty =
DependencyProperty.Register("SearchButtonSize", typeof(double), typeof(SearchBar), new PropertyMetadata(30.0));
public double CloseButtonSize
{
get { return (double)GetValue(CloseButtonSizeProperty); }
set { SetValue(CloseButtonSizeProperty, value); }
}
public static readonly DependencyProperty CloseButtonSizeProperty =
DependencyProperty.Register("CloseButtonSize", typeof(double), typeof(SearchBar), new PropertyMetadata(30.0));
#endregion
public SearchBar()
{
InitializeComponent();
_searchIcons = new Dictionary<enumF4sdSearchResultClass, UIElement>()
{
{ enumF4sdSearchResultClass.Phone, PhoneCallIndicator },
{ enumF4sdSearchResultClass.User, UserCallIndicator },
{ enumF4sdSearchResultClass.Computer, ComputerCallIndicator }
};
}
public void BlurInvoker_IsActiveChanged(object sender, DependencyPropertyChangedEventArgs e)
{
BlurInvoker.InvokeVisibilityChanged(this, new EventArgs());
if (e.NewValue is bool newVisible)
{
if (newVisible == false)
{
SearchTextBox.IsEnabled = true;
SearchButton.Visibility = Visibility.Visible;
WarningIndicator.Visibility = Visibility.Collapsed;
TicketOverview.Instance?.ResetSelection();
foreach (var Entry in _searchIcons.Values)
Entry.Visibility = Visibility.Collapsed;
}
SetApiStatus();
}
if (Visibility == Visibility.Visible)
{
var _h = Dispatcher.BeginInvoke((Action)delegate { Keyboard.Focus(SearchTextBox); }, DispatcherPriority.Render);
}
}
public void Clear()
{
SearchStatus = eSearchStatus.message;
SearchTextBox.Text = null;
}
public void ActivateManualSearch()
{
SearchStatus = eSearchStatus.active;
SearchButton.Visibility = Visibility.Visible;
WarningIndicator.Visibility = Visibility.Collapsed;
foreach (var Entry in _searchIcons.Values)
Entry.Visibility = Visibility.Collapsed;
SearchTextBox.Text = null;
SearchTextBox.IsEnabled = true;
SearchTextBox.Focus();
Keyboard.Focus(SearchTextBox);
}
public void SetSearchText(string search)
{
SearchStatus = eSearchStatus.active;
SearchTextBox.Text = search;
SearchTextBox.CaretIndex = search.Length;
SearchTextBox.CaretIndex = search?.Length ?? 0;
SearchTextBox.Focus();
Keyboard.Focus(SearchTextBox);
}
public void FocusInput()
{
SearchTextBox.Focus();
Keyboard.Focus(SearchTextBox);
}
@@ -157,165 +156,18 @@ namespace FasdDesktopUi.Basics.UserControls
Dispatcher.Invoke(() => SearchSpinner.Visibility = visibility);
}
public async Task SetFixedSearchResultAsync(enumF4sdSearchResultClass Class, string search, cFilteredResults result)
{
SearchStatus = eSearchStatus.fixedResult;
SearchTextBox.IsEnabled = false;
SearchButton.Visibility = Visibility.Collapsed;
WarningIndicator.Visibility = Visibility.Collapsed;
foreach (var entryIcon in _searchIcons)
{
if (Class == entryIcon.Key)
entryIcon.Value.Visibility = Visibility.Visible;
else
entryIcon.Value.Visibility = Visibility.Collapsed;
}
SearchTextBox.Text = search;
if (ChangedSearchValue != null)
await ChangedSearchValue.Invoke(result);
}
public void SetApiStatus()
{
try
{
var Status = cConnectionStatusHelper.Instance?.ApiConnectionStatus;
if (Status == null)
return;
bool IsEnabled = false;
string txt = null;
switch (Status)
{
case cConnectionStatusHelper.enumOnlineStatus.online:
IsEnabled = true;
break;
case cConnectionStatusHelper.enumOnlineStatus.connectionError:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ConnectError");
break;
case cConnectionStatusHelper.enumOnlineStatus.incompatibleServerVersion:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.IncompatibleVersion");
break;
case cConnectionStatusHelper.enumOnlineStatus.serverStarting:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ServerStarting");
break;
case cConnectionStatusHelper.enumOnlineStatus.serverNotConfigured:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ServerNotConfigured");
break;
case cConnectionStatusHelper.enumOnlineStatus.illegalConfig:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.IllegalConfig");
break;
case cConnectionStatusHelper.enumOnlineStatus.unauthorized:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.Unauthorized");
break;
default:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.Offline");
break;
}
if (!IsEnabled)
{
SearchStatus = eSearchStatus.message;
SearchTextBox.Text = txt;
SearchTextBox.IsEnabled = false;
WarningIndicator.Visibility = Visibility.Visible;
SearchButton.Visibility = Visibility.Collapsed;
foreach (var Entry in _searchIcons.Values)
Entry.Visibility = Visibility.Collapsed;
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
}
}
private async Task CancelRunningSearchTaskAsync()
{
// cancel the search task, in case of a running search task
lock (_currentSearchTaskLock)
{
if (_currentSearchTaskToken != null)
{
LogEntry("Canceling current running search...");
_currentSearchTaskToken.Cancel(true);
_currentSearchTaskToken = null;
}
}
// send a stop to the server, in case of a running search task
Guid? currentTaskId = null;
lock (_currentSearchTaskLock)
{
if (_currentSearchTaskId != null)
{
currentTaskId = _currentSearchTaskId;
_currentSearchTaskId = null;
}
}
if (currentTaskId != null)
{
LogEntry("Sending a search stop...");
await cFasdCockpitCommunicationBase.Instance.GetSearchResultsStop((Guid)currentTaskId, CancellationToken.None);
}
}
private async void UpdateSearchResultsTick(object sender, EventArgs e)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
_searchTimer.Stop();
await CancelRunningSearchTaskAsync();
lock (_currentSearchTaskLock)
{
LogEntry("Start running new search...");
SearchValueChanged?.Invoke(this, SearchValue);
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
}
private void HandleSearchValueChanged()
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
if (_searchTimer.IsEnabled)
_searchTimer.Stop();
try
{
if (!SearchTextBox.IsEnabled)
return;
_searchTimer.Start();
}
if (_searchTimer.IsEnabled)
_searchTimer.Stop();
_searchTimer.Start();
_ = Task.Run(async () => { await CancelRunningSearchTaskAsync(); });
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
private void SearchTimerTick(object sender, EventArgs e)
{
_searchTimer.Stop();
SearchValueChanged?.Invoke(this, SearchValue);
}
private void SearchButton_Click(object sender, InputEventArgs e)
@@ -323,40 +175,28 @@ namespace FasdDesktopUi.Basics.UserControls
SearchTextBox.Focus();
}
#region CancledSearch Event
public static readonly RoutedEvent CancledSearchEvent = EventManager.RegisterRoutedEvent("CancledSearch", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SearchBar));
public event RoutedEventHandler CancledSearch
{
add { AddHandler(CancledSearchEvent, value); }
remove { RemoveHandler(CancledSearchEvent, value); }
}
private void RaiseCancledSearchEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(CancledSearchEvent);
RaiseEvent(newEventArgs);
}
#endregion
private void CloseButton_Click(object sender, InputEventArgs e)
{
RaiseCancledSearchEvent();
if (cConnectionStatusHelper.Instance?.ApiConnectionStatus == cConnectionStatusHelper.enumOnlineStatus.online)
SearchTextBox.Text = null;
CancledSearchAction?.Invoke();
RaiseEvent(new RoutedEventArgs(CancelledSearchEvent));
}
private void SearchBar_Loaded(object sender, RoutedEventArgs e)
{
_searchTimer.Stop();
_searchTimer.Interval = TimeSpan.FromMilliseconds(constTimeBetweenKeystrokes);
_searchTimer.Tick += UpdateSearchResultsTick;
_searchTimer.Interval = DebounceInterval;
_searchTimer.Tick += SearchTimerTick;
BackgroundBorder.CornerRadius = new CornerRadius(BackgroundBorder.ActualHeight / 2.0);
}
internal void ActivateManualSearch()
{
Search.Clear();
Search.IsInputEnabled = true;
Dispatcher.BeginInvoke(new Action(() =>
{
Search.FocusInput();
}), DispatcherPriority.Input);
}
}
}

View File

@@ -197,7 +197,7 @@ namespace FasdDesktopUi.Basics.UserControls
MenuData = new cMenuDataBase()
{
MenuText = cMultiLanguageSupport.GetItem("SearchBar.NoResults"),
MenuIcon = new IconData(enumInternIcons.menuBar_search_noResults)
MenuIcon = new cMenuDataBase.MenuIconInfo(new IconData(enumInternIcons.menuBar_search_noResults))
}
};
MainStackPanel.Children.Add(resultItemControl);
@@ -236,7 +236,7 @@ namespace FasdDesktopUi.Basics.UserControls
var menuData = new cMenuDataBase() { MenuText = historyEntry.DisplayText, UiAction = new cUiProcessSearchHistoryEntry(historyEntry) };
if (historyEntry.isSeen)
{
menuData.MenuIcon = new IconData(MaterialIcons.MaterialIconType.ic_visibility);
menuData.MenuIcon = new cMenuDataBase.MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_visibility));
menuData.MenuIconSize = 0.75;
}

View File

@@ -5,31 +5,33 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:config="clr-namespace:C4IT.FASD.Base;assembly=F4SD-Cockpit-Client-Base"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vd="clr-namespace:FasdDesktopUi.Basics.Converter"
xmlns:vc="clr-namespace:C4IT.MultiLanguage;assembly=F4SD-Cockpit-Client-Base"
mc:Ignorable="d"
Initialized="UserControl_Initialized">
Initialized="UserControl_Initialized">
<UserControl.Resources>
<vd:LanguageDefinitionsConverter x:Key="LanguageConverter"/>
<!-- Style für den Hovereffekt -->
<Style x:Key="PauseButtonHoverStyle" TargetType="Border">
<Setter Property="Background" Value="Transparent"/>
<vd:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<Style x:Key="PauseButtonHoverStyle"
TargetType="Border">
<Setter Property="Background"
Value="Transparent" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource Background.Menu.Icon.Hover}"/>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="{DynamicResource Background.Menu.Icon.Hover}" />
</Trigger>
</Style.Triggers>
</Style>
</Style>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border Padding="8"
@@ -45,71 +47,72 @@
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TimerView.Time.ToolTip}"
Foreground="{DynamicResource Color.Menu.Icon}" />
</Border>
<Border Padding="20 5 5 5"
<Border Padding="20 5 5 5"
Grid.Column="1"
Width="Auto"
Height="33"
Cursor="Hand"
HorizontalAlignment="Center"
VerticalAlignment="Center"
CornerRadius="5"
CornerRadius="5"
Margin="-5 0 0 0"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TimerView.Pausebutton.ToolTip}"
Style="{DynamicResource PauseButtonHoverStyle}"
MouseLeftButtonUp="Border_MouseLeftButtonUp" TouchDown="Border_TouchDown"
>
MouseLeftButtonUp="Border_Click"
TouchDown="Border_Click">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ico:AdaptableIcon Grid.Column="1"
<ico:AdaptableIcon Grid.Column="1"
x:Name="PauseButton"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="-15 0 5 0"
Margin="-15 0 5 0"
Panel.ZIndex="2"
BorderPadding="0"
IconHeight="22"
IconWidth="22"
SelectedMaterialIcon="ic_pause_circle_outline"
SelectedMaterialIcon="ic_pause_circle_outline"
IconBackgroundColor="Transparent">
<ico:AdaptableIcon.Resources>
<Style TargetType="ico:AdaptableIcon"
BasedOn="{StaticResource Menu.MenuBar.PinnedIcon.Pinned}">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource FontColor.Menu.Categories}"/>
Value="{DynamicResource FontColor.Menu.Categories}" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource FontColor.Menu.Categories.Hover}"/>
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.FunctionMarker}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ico:AdaptableIcon.Resources>
</ico:AdaptableIcon>
<TextBlock Grid.Column="2" Text="Pause">
<TextBlock Grid.Column="2"
Text="Pause">
<TextBlock.Resources>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment"
Value="Center"/>
Value="Center" />
<Setter Property="HorizontalAlignment"
Value="Center"/>
Value="Center" />
<Setter Property="FontSize"
Value="16"/>
Value="16" />
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories}"/>
Value="{DynamicResource FontColor.Menu.Categories}" />
<Setter Property="Margin"
Value="0 0 0 2"/>
Value="0 0 0 2" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories.Hover}"/>
Value="{DynamicResource Color.FunctionMarker}" />
</DataTrigger>
</Style.Triggers>
</Style>

View File

@@ -15,18 +15,18 @@ namespace FasdDesktopUi.Basics.UserControls
public event EventHandler<EventArgs> OnPauseStarted;
private static List<DateTime> startTimes = new List<DateTime>();
private static List<DateTime> endTimes = new List<DateTime>();
private static List<DateTime> pausedTimesStart = new List<DateTime>();
private static List<DateTime> pausedTimesEnd = new List<DateTime>();
private static readonly List<DateTime> _startTimes = new List<DateTime>();
private static readonly List<DateTime> _endTimes = new List<DateTime>();
private static readonly List<DateTime> _pausedTimesStart = new List<DateTime>();
private static readonly List<DateTime> _pausedTimesEnd = new List<DateTime>();
public static List<cF4SDCaseTime> caseTimes = new List<cF4SDCaseTime>();
private static Dictionary<string, object> finalWorkingTimes = new Dictionary<string, object>();
public static List<cF4SDCaseTime> CaseTimes = new List<cF4SDCaseTime>();
private static Dictionary<string, object> _finalWorkingTimes = new Dictionary<string, object>();
private static DispatcherTimer timer;
private static TimeSpan elapsedTime;
private static TimeSpan totalPausedTime = TimeSpan.Zero;
private static TimeSpan pauseDuration;
private static DispatcherTimer _timer;
private static TimeSpan _elapsedTime;
private static TimeSpan _totalPausedTime = TimeSpan.Zero;
private static TimeSpan _pauseDuration;
#endregion
@@ -39,13 +39,13 @@ namespace FasdDesktopUi.Basics.UserControls
public static void ResetTimer()
{
startTimes.Clear();
endTimes.Clear();
pausedTimesEnd.Clear();
pausedTimesStart.Clear();
finalWorkingTimes.Clear();
elapsedTime = TimeSpan.Zero;
caseTimes.Clear();
_startTimes.Clear();
_endTimes.Clear();
_pausedTimesEnd.Clear();
_pausedTimesStart.Clear();
_finalWorkingTimes.Clear();
_elapsedTime = TimeSpan.Zero;
CaseTimes.Clear();
StartTimer();
}
@@ -54,8 +54,8 @@ namespace FasdDesktopUi.Basics.UserControls
{
try
{
startTimes?.Add(DateTime.UtcNow);
timer?.Start();
_startTimes?.Add(DateTime.UtcNow);
_timer?.Start();
}
catch (Exception E)
{
@@ -67,8 +67,8 @@ namespace FasdDesktopUi.Basics.UserControls
{
try
{
endTimes?.Add(DateTime.UtcNow);
timer?.Stop();
_endTimes?.Add(DateTime.UtcNow);
_timer?.Stop();
UpdateTimerControl();
}
catch (Exception E)
@@ -83,7 +83,7 @@ namespace FasdDesktopUi.Basics.UserControls
{
ResetTimer();
timer = new DispatcherTimer(TimeSpan.FromSeconds(1.0), DispatcherPriority.Loaded, new EventHandler((s, args) =>
_timer = new DispatcherTimer(TimeSpan.FromSeconds(1.0), DispatcherPriority.Loaded, new EventHandler((s, args) =>
{
try { UpdateTimerControl(); }
catch { }
@@ -100,8 +100,8 @@ namespace FasdDesktopUi.Basics.UserControls
{
try
{
TimerControl.Text = elapsedTime.ToString(@"hh\:mm\:ss");
elapsedTime = elapsedTime.Add(TimeSpan.FromSeconds(1.0));
TimerControl.Text = _elapsedTime.ToString(@"hh\:mm\:ss");
_elapsedTime = _elapsedTime.Add(TimeSpan.FromSeconds(1.0));
}
catch (Exception E)
{
@@ -113,44 +113,44 @@ namespace FasdDesktopUi.Basics.UserControls
{
try
{
var currentDate = DateTime.Now.Date.ToString("d");
var startDateTime = startTimes.First();
var currentDate = DateTime.UtcNow.Date.ToString("d");
var startDateTime = _startTimes.First();
var endDateTime = DateTime.UtcNow;
var bruttoWorkingTime = TimeSpan.Zero;
var nettoWorkingTime = TimeSpan.Zero;
if (pausedTimesStart.Count == 0)
if (_pausedTimesStart.Count == 0)
{
totalPausedTime = TimeSpan.Zero;
_totalPausedTime = TimeSpan.Zero;
}
if (pausedTimesEnd.Count > 0)
if (_pausedTimesEnd.Count > 0)
{
totalPausedTime = TimeSpan.Zero;
_totalPausedTime = TimeSpan.Zero;
for (int i = 0; i < pausedTimesStart.Count; i++)
for (int i = 0; i < _pausedTimesStart.Count; i++)
{
var start = pausedTimesStart[i];
var end = pausedTimesEnd[i];
var start = _pausedTimesStart[i];
var end = _pausedTimesEnd[i];
pauseDuration = end - start;
_pauseDuration = end - start;
totalPausedTime += pauseDuration;
_totalPausedTime += _pauseDuration;
}
}
bruttoWorkingTime = endDateTime - startDateTime;
nettoWorkingTime = bruttoWorkingTime - totalPausedTime;
nettoWorkingTime = bruttoWorkingTime - _totalPausedTime;
finalWorkingTimes = new Dictionary<string, object>()
_finalWorkingTimes = new Dictionary<string, object>()
{
{"CurrentDate", currentDate},
{"StartTime", startTimes.First()},
{"StartTime", _startTimes.First()},
{"EndTime", endDateTime },
{"BruttoWorkingTime", bruttoWorkingTime },
{"NettoWorkingTime", nettoWorkingTime.TotalSeconds },
{"TotalPausedTime", totalPausedTime }
{"TotalPausedTime", _totalPausedTime }
};
}
catch (Exception E)
@@ -158,7 +158,7 @@ namespace FasdDesktopUi.Basics.UserControls
LogException(E);
}
return finalWorkingTimes;
return _finalWorkingTimes;
}
#endregion
@@ -169,13 +169,13 @@ namespace FasdDesktopUi.Basics.UserControls
{
try
{
if (timer?.IsEnabled == true)
if (_timer?.IsEnabled == true)
return;
timer?.Start();
pausedTimesEnd?.Add(DateTime.UtcNow);
_timer?.Start();
_pausedTimesEnd?.Add(DateTime.UtcNow);
caseTimes.Add(new cF4SDCaseTime()
CaseTimes.Add(new cF4SDCaseTime()
{
StatusId = CaseStatus.InProgress,
CaseTime = DateTime.UtcNow
@@ -191,10 +191,10 @@ namespace FasdDesktopUi.Basics.UserControls
{
try
{
timer?.Stop();
pausedTimesStart?.Add(DateTime.UtcNow);
_timer?.Stop();
_pausedTimesStart?.Add(DateTime.UtcNow);
caseTimes.Add(new cF4SDCaseTime()
CaseTimes.Add(new cF4SDCaseTime()
{
StatusId = CaseStatus.OnHold,
CaseTime = DateTime.UtcNow
@@ -209,17 +209,9 @@ namespace FasdDesktopUi.Basics.UserControls
}
}
private void Border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
PauseButton_Click();
}
private void Border_Click(object sender, InputEventArgs e)
=> PauseButton_Click();
#endregion
private void Border_TouchDown(object sender, TouchEventArgs e)
{
PauseButton_Click();
}
}
}

View File

@@ -1,15 +1,13 @@
using C4IT.F4SD.DisplayFormatting;
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UserControls;
using FasdDesktopUi.Basics.UserControls.AdaptableIcon;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
@@ -362,7 +360,7 @@ namespace FasdDesktopUi.Basics
try
{
FormattingOptions options = new FormattingOptions() { ReferenceDate = DateTime.UtcNow.AddDays(_v.ReferenceDays), TimeZone = TimeZoneInfo.Local };
RawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
RawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
var _strVal = RawValueFormatter.GetDisplayValue(_v.Value, _v.StateDefinition.DisplayType, options);
@@ -468,5 +466,11 @@ namespace FasdDesktopUi.Basics
#endregion
public static string GetShortDatePattern()
{
string datePattern = cFasdCockpitConfig.Instance.SelectedCulture.DateTimeFormat.ShortDatePattern;
datePattern = Regex.Replace(datePattern, @"(^|[/.\-\s])y{1,4}($|[/.\-\s]?)", "");
return datePattern.Trim('/', '.', '-', ' ');
}
}
}

View File

@@ -192,15 +192,15 @@
<Language Lang="DE">Auswählen</Language>
</UIItem>
<UIItem Name="Header.Select.MobileDevice">
<Language Lang="EN">Select</Language>
<Language Lang="DE">Auswählen</Language>
</UIItem>
<UIItem Name="Header.Select.MobileDevice">
<Language Lang="EN">Select</Language>
<Language Lang="DE">Auswählen</Language>
</UIItem>
<UIItem Name="Header.Select.Ticket">
<Language Lang="EN">Select</Language>
<Language Lang="DE">Auswählen</Language>
</UIItem>
<UIItem Name="Header.Select.Ticket">
<Language Lang="EN">Select</Language>
<Language Lang="DE">Auswählen</Language>
</UIItem>
<UIItem Name="Header.Create.Ticket">
<Language Lang="EN">Create ticket</Language>
@@ -237,15 +237,15 @@
<Language Lang="DE">Es wurden keine Session für diesen Fall gefunden.</Language>
</UIItem>
<UIItem Name="Header.NotFound.MobileDevice">
<Language Lang="EN">There were no mobile device found for this case.</Language>
<Language Lang="DE">Es wurden keine mobilen Geräte für diesen Fall gefunden.</Language>
</UIItem>
<UIItem Name="Header.NotFound.MobileDevice">
<Language Lang="EN">There were no mobile device found for this case.</Language>
<Language Lang="DE">Es wurden keine mobilen Geräte für diesen Fall gefunden.</Language>
</UIItem>
<UIItem Name="Header.NotFound.Tickets">
<Language Lang="EN">There were no tickets found for this case.</Language>
<Language Lang="DE">Es wurden keine Tickets für diesen Fall gefunden.</Language>
</UIItem>
<UIItem Name="Header.NotFound.Tickets">
<Language Lang="EN">There were no tickets found for this case.</Language>
<Language Lang="DE">Es wurden keine Tickets für diesen Fall gefunden.</Language>
</UIItem>
<!--SearchBar-->
<UIItem Name="Searchbar.Status.Offline">
@@ -334,14 +334,10 @@
</UIItem>
<UIItem Name="Searchbar.NewSearch.ActiveSupportCase">
<Language Lang="EN">
You currently have an open support case.
How would you like to proceed?
</Language>
<Language Lang="DE">
Sie haben aktuell einen noch nicht abgeschlossenen Support Fall.
Wie möchten Sie fortfahren?
</Language>
<Language Lang="EN">You currently have an open support case.
How would you like to proceed?</Language>
<Language Lang="DE">Sie haben aktuell einen noch nicht abgeschlossenen Support Fall.
Wie möchten Sie fortfahren?</Language>
</UIItem>
<UIItem Name="Searchbar.NewSearch.ActiveSupportCase.ContinueCase">
@@ -473,7 +469,48 @@
<Language Lang="DE">Geschlossen</Language>
</UIItem>
<UIItem Name="TicketOverview.Notification.Title">
<UIItem Name="Searchbar.Item.Ticket.Active">
<Language Lang="EN">Ticket</Language>
<Language Lang="DE">Ticket</Language>
</UIItem>
<UIItem Name="Searchbar.Item.Ticket.Closed">
<Language Lang="EN">Closed ticket</Language>
<Language Lang="DE">geschlossenes Ticket</Language>
</UIItem>
<UIItem Name="Searchbar.Item.Unclassified.Active">
<Language Lang="EN">Ticket (not classified)</Language>
<Language Lang="DE">Ticket (nicht klassifiziert)</Language>
</UIItem>
<UIItem Name="Searchbar.Item.Unclassified.Closed">
<Language Lang="EN">Closed ticket (not classified)</Language>
<Language Lang="DE">geschlossenes Ticket (nicht klassifiziert)</Language>
</UIItem>
<UIItem Name="Searchbar.Item.Incident.Active">
<Language Lang="EN">Incident</Language>
<Language Lang="DE">Störung</Language>
</UIItem>
<UIItem Name="Searchbar.Item.Incident.Closed">
<Language Lang="EN">Closed incident</Language>
<Language Lang="DE">geschlossene Störung</Language>
</UIItem>
<UIItem Name="Searchbar.Item.ServiceRequest.Active">
<Language Lang="EN">Service request</Language>
<Language Lang="DE">Serviceanfrage</Language>
</UIItem>
<UIItem Name="Searchbar.Item.ServiceRequest.Closed">
<Language Lang="EN">Closed service request</Language>
<Language Lang="DE">geschlossene Serviceanfrage</Language>
</UIItem>
<!--Ticket Overview-->
<UIItem Name="TicketOverview.Notification.Title">
<Language Lang="EN">Ticket overview updated</Language>
<Language Lang="DE">Ticketübersicht aktualisiert</Language>
</UIItem>
@@ -503,30 +540,30 @@
<Language Lang="DE">Eigene Tickets</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Personal.Incidents">
<Language Lang="EN">My incidents</Language>
<Language Lang="DE">Eigene Störungen</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Personal.UnassignedTickets">
<Language Lang="EN">My unassigned</Language>
<Language Lang="DE">Eigener Eingang</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.Tickets">
<Language Lang="EN">Role tickets</Language>
<Language Lang="DE">Rollentickets</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Personal.Incidents">
<Language Lang="EN">My incidents</Language>
<Language Lang="DE">Eigene Störungen</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.Incidents">
<Language Lang="EN">Role incidents</Language>
<Language Lang="DE">Rollenstörungen</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.UnassignedTickets">
<Language Lang="EN">Role unassigned</Language>
<Language Lang="DE">Rolleneingang</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Personal.UnassignedTickets">
<Language Lang="EN">My unassigned</Language>
<Language Lang="DE">Eigener Eingang</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.Tickets">
<Language Lang="EN">Role tickets</Language>
<Language Lang="DE">Rollentickets</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.Incidents">
<Language Lang="EN">Role incidents</Language>
<Language Lang="DE">Rollenstörungen</Language>
</UIItem>
<UIItem Name="TicketOverview.ScopeRow.Role.UnassignedTickets">
<Language Lang="EN">Role unassigned</Language>
<Language Lang="DE">Rolleneingang</Language>
</UIItem>
<!--Menu-->
<UIItem Name="Menu.About">
@@ -555,14 +592,10 @@
</UIItem>
<UIItem Name="Menu.RestartDialog.Text">
<Language Lang="EN">
Do you really want to restart the F4SD Cockpit?
All open cases will be closed.
</Language>
<Language Lang="DE">
Wollen Sie das F4SD Cockpit wirklich schließen?
Alle offenen Fälle werden dabei geschlossen.
</Language>
<Language Lang="EN">Do you really want to restart the F4SD Cockpit?
All open cases will be closed.</Language>
<Language Lang="DE">Wollen Sie das F4SD Cockpit wirklich schließen?
Alle offenen Fälle werden dabei geschlossen.</Language>
</UIItem>
<UIItem Name="Menu.Quit">
@@ -581,16 +614,12 @@
</UIItem>
<UIItem Name="Menu.SelectLanguage.RestartDialog.Text">
<Language Lang="EN">
Changes to the language settings will not take effect until the environment is restarted. All open sessions will be lost.
<Language Lang="EN">Changes to the language settings will not take effect until the environment is restarted. All open sessions will be lost.
Do you want to restart the F4SD Cockpit now?
</Language>
<Language Lang="DE">
Änderungen an den Spracheinstellungen treten erst in Kraft, nachdem die Umgebung neu gestartet wurde. Alle offenen Fälle gehen dabei verloren.
Do you want to restart the F4SD Cockpit now?</Language>
<Language Lang="DE">Änderungen an den Spracheinstellungen treten erst in Kraft, nachdem die Umgebung neu gestartet wurde. Alle offenen Fälle gehen dabei verloren.
Wollen Sie das F4SD Cockpit jetzt neu starten?
</Language>
Wollen Sie das F4SD Cockpit jetzt neu starten?</Language>
</UIItem>
<UIItem Name="Menu.SelectLanguage.Default">
@@ -613,15 +642,16 @@
<Language Lang="DE">Position der Favoriten Leiste</Language>
</UIItem>
<UIItem Name="Menu.UseGamification">
<Language Lang="EN">Use level progression system</Language>
<Language Lang="DE">Levelfortschritts-System verwenden</Language>
</UIItem>
<UIItem Name="Menu.TrademarkNotice">
<Language Lang="EN">
F4SD® is a registered word mark of Consulting4IT GmbH.
All rights, including but not limited to, ownership, intellectual property, and exclusive usage of the trademark, are fully held by Consulting4IT GmbH. Any unauthorized use or imitation of the mark is legally prohibited and may lead to civil and criminal penalties.
</Language>
<Language Lang="DE">
F4SD® ist eine eingetragene Wortmarke der Consulting4IT GmbH.
Alle Rechte, einschließlich, aber nicht beschränkt auf, das Eigentum, das geistige Eigentum und die exklusive Nutzung der Marke, liegen vollständig bei der Consulting4IT GmbH. Jegliche unautorisierte Nutzung oder Nachahmung der Marke ist gesetzlich verboten und kann zu zivil- und strafrechtlichen Sanktionen führen.
</Language>
<Language Lang="EN">F4SD® is a registered word mark of Consulting4IT GmbH.
All rights, including but not limited to, ownership, intellectual property, and exclusive usage of the trademark, are fully held by Consulting4IT GmbH. Any unauthorized use or imitation of the mark is legally prohibited and may lead to civil and criminal penalties.</Language>
<Language Lang="DE">F4SD® ist eine eingetragene Wortmarke der Consulting4IT GmbH.
Alle Rechte, einschließlich, aber nicht beschränkt auf, das Eigentum, das geistige Eigentum und die exklusive Nutzung der Marke, liegen vollständig bei der Consulting4IT GmbH. Jegliche unautorisierte Nutzung oder Nachahmung der Marke ist gesetzlich verboten und kann zu zivil- und strafrechtlichen Sanktionen führen.</Language>
</UIItem>
<!--PausePage-->
@@ -718,6 +748,11 @@
<Language Lang="DE">Führe Quick Action aus.</Language>
</UIItem>
<UIItem Name="QuickAction.Phoenix.StartViewer">
<Language Lang="EN">Start F4SD phoenix viewer.</Language>
<Language Lang="DE">Starte F4SD Phoenix Viewer.</Language>
</UIItem>
<UIItem Name="QuickAction.Local.Load">
<Language Lang="EN">Load and run local script.</Language>
<Language Lang="DE">Lade und führe lokales Skript aus.</Language>
@@ -889,15 +924,15 @@
<Language Lang="DE">Die Quick Action &lt;b&gt;"{0}"&lt;/b&gt; wurde durch F4SD remote auf dem Gerät &lt;b&gt;"{1}"&lt;/b&gt; am {2} UTC &lt;b&gt;{3}&lt;/b&gt;ausgeführt.</Language>
</UIItem>
<UIItem Name="QuickAction.RemoteSession.Copy.Description">
<Language Lang="EN">The Quick Action '{0}' was {3}executed remotely by F4SD for the session '{1}' at {2} UTC.</Language>
<Language Lang="DE">Die Quick Action "{0}" wurde durch F4SD remote für die Session "{1}" am {2} UTC {3}ausgeführt.</Language>
</UIItem>
<UIItem Name="QuickAction.RemoteSession.Copy.Description">
<Language Lang="EN">The Quick Action '{0}' was {3}executed remotely by F4SD for the session '{1}' at {2} UTC.</Language>
<Language Lang="DE">Die Quick Action "{0}" wurde durch F4SD remote für die Session "{1}" am {2} UTC {3}ausgeführt.</Language>
</UIItem>
<UIItem Name="QuickAction.RemoteSession.Copy.Description.Html">
<Language Lang="EN">The Quick Action &lt;b&gt;'{0}'&lt;/b&gt; was &lt;b&gt;{3}&lt;/b&gt;executed remotely by F4SD on the session &lt;b&gt;'{1}'&lt;/b&gt; at {2} UTC.</Language>
<Language Lang="DE">Die Quick Action &lt;b&gt;"{0}"&lt;/b&gt; wurde durch F4SD remote für die Session &lt;b&gt;"{1}"&lt;/b&gt; am {2} UTC &lt;b&gt;{3}&lt;/b&gt;ausgeführt.</Language>
</UIItem>
<UIItem Name="QuickAction.RemoteSession.Copy.Description.Html">
<Language Lang="EN">The Quick Action &lt;b&gt;'{0}'&lt;/b&gt; was &lt;b&gt;{3}&lt;/b&gt;executed remotely by F4SD on the session &lt;b&gt;'{1}'&lt;/b&gt; at {2} UTC.</Language>
<Language Lang="DE">Die Quick Action &lt;b&gt;"{0}"&lt;/b&gt; wurde durch F4SD remote für die Session &lt;b&gt;"{1}"&lt;/b&gt; am {2} UTC &lt;b&gt;{3}&lt;/b&gt;ausgeführt.</Language>
</UIItem>
<UIItem Name="QuickAction.Local.Copy.Description">
<Language Lang="EN">The Quick Action '{0}' was {3}executed local by F4SD for the device '{1}' at {2} UTC.</Language>
@@ -1131,25 +1166,17 @@
</UIItem>
<UIItem Name="PhoneSettings.Tapi.Disabled.PhoneSupportDisabled">
<Language Lang="EN">
Phone support was disabled.
Enable phone support first.
</Language>
<Language Lang="DE">
Telefonie-Unterstützung wurde deaktiviert.
Aktivieren Sie zuerst die Telefon-Unterstützung.
</Language>
<Language Lang="EN">Phone support was disabled.
Enable phone support first.</Language>
<Language Lang="DE">Telefonie-Unterstützung wurde deaktiviert.
Aktivieren Sie zuerst die Telefon-Unterstützung.</Language>
</UIItem>
<UIItem Name="PhoneSettings.Tapi.Disabled.SwyxItNativeEnabled">
<Language Lang="EN">
SwyxIt! native was enabled.
Disable SwyxIt! native first.
</Language>
<Language Lang="DE">
Natives SwyxIt! wurde aktiviert.
Deaktivieren Sie zuerst natives SwyxIt!.
</Language>
<Language Lang="EN">SwyxIt! native was enabled.
Disable SwyxIt! native first.</Language>
<Language Lang="DE">Natives SwyxIt! wurde aktiviert.
Deaktivieren Sie zuerst natives SwyxIt!.</Language>
</UIItem>
<UIItem Name="PhoneSettings.Tapi.Disabled.NoLine">
@@ -1163,16 +1190,12 @@
</UIItem>
<UIItem Name="PhoneSettings.RestartDialog.Text">
<Language Lang="EN">
Changes to the phone support will not take effect until the environment is restarted. All open sessions will be lost.
<Language Lang="EN">Changes to the phone support will not take effect until the environment is restarted. All open sessions will be lost.
Do you want to restart the F4SD Cockpit now?
</Language>
<Language Lang="DE">
Änderungen an Telefonie-Unterstützung treten erst in Kraft, nachdem die Umgebung neu gestartet wurde. Alle offenen Fälle gehen dabei verloren.
Do you want to restart the F4SD Cockpit now?</Language>
<Language Lang="DE">Änderungen an Telefonie-Unterstützung treten erst in Kraft, nachdem die Umgebung neu gestartet wurde. Alle offenen Fälle gehen dabei verloren.
Wollen Sie das F4SD Cockpit jetzt neu starten?
</Language>
Wollen Sie das F4SD Cockpit jetzt neu starten?</Language>
</UIItem>
@@ -1223,16 +1246,12 @@
</UIItem>
<UIItem Name="M42Settings.ChangedInfoDialog.Text">
<Language Lang="EN">
Changes in the Matrix42 authentification will not take effect until the environment is restarted. All open sessions will be lost.
<Language Lang="EN">Changes in the Matrix42 authentification will not take effect until the environment is restarted. All open sessions will be lost.
Do you want to restart the F4SD Cockpit now?
</Language>
<Language Lang="DE">
Die Änderungen bei der Matrix42 Anmeldung treten erst in Kraft, nachdem die Umgebung neu gestartet wurde. Alle offenen Fälle gehen dabei verloren.
Do you want to restart the F4SD Cockpit now?</Language>
<Language Lang="DE">Die Änderungen bei der Matrix42 Anmeldung treten erst in Kraft, nachdem die Umgebung neu gestartet wurde. Alle offenen Fälle gehen dabei verloren.
Wollen Sie das F4SD Cockpit jetzt neu starten?
</Language>
Wollen Sie das F4SD Cockpit jetzt neu starten?</Language>
</UIItem>
<UIItem Name="M42Settings.LogonMethod.Header">
@@ -1359,8 +1378,8 @@
<!--Dialog.CloseCase-->
<UIItem Name="Dialog.CloseCase">
<Language Lang="EN">Close case</Language>
<Language Lang="DE">Fall abschließen</Language>
<Language Lang="EN">Document case</Language>
<Language Lang="DE">Fall dokumentieren</Language>
</UIItem>
<UIItem Name="Dialog.CloseCase.Title">
@@ -1715,13 +1734,36 @@
<Language Lang="DE">Tickets</Language>
</UIItem>
<UIItem Name="TicketOverview.Row.Heading.Incidents">
<Language Lang="EN">Incidents</Language>
<Language Lang="DE">Störungen</Language>
</UIItem>
<UIItem Name="TicketOverview.Row.Heading.UnassignedTickets">
<Language Lang="EN">Unassigned</Language>
<Language Lang="DE">Eingang</Language>
</UIItem>
</UILanguage>
<UIItem Name="TicketOverview.Row.Heading.Incidents">
<Language Lang="EN">Incidents</Language>
<Language Lang="DE">Störungen</Language>
</UIItem>
<UIItem Name="TicketOverview.Row.Heading.UnassignedTickets">
<Language Lang="EN">Unassigned</Language>
<Language Lang="DE">Eingang</Language>
</UIItem>
<UIItem Name="Gamification.LevelUp.Continue">
<Language Lang="EN">Let's continue!</Language>
<Language Lang="DE">Weiter geht's!</Language>
</UIItem>
<UIItem Name="RemoteConnection.Button.Disabled">
<Language Lang="EN">Remote connection is currenlty only available for computers</Language>
<Language Lang="DE">Remote Verbindung wird derzeit nur für Computer unterstützt</Language>
</UIItem>
<UIItem Name="RemoteConnection.Disabled.UnhealthyService">
<Language Lang="EN">Remote connection services are currently unavailable</Language>
<Language Lang="DE">Die Dienste für Remote Verbindung sind derzeit gestört</Language>
</UIItem>
<UIItem Name="Quickaction.Title.LogOff">
<Language Lang="EN">Logoff Pending</Language>
<Language Lang="DE">Abmeldung bevorstehend</Language>
</UIItem>
<UIItem Name="Quickaction.Text.LogOff">
<Language Lang="EN">Urgent maintenance required. You will be logged out shortly. Please save your data.</Language>
<Language Lang="DE">Eine dringende Wartung muss durchgeführt werden. Sie werden in Kürze abgemeldet. Bitte speichern Sie Ihre Daten.</Language>
</UIItem>
</UILanguage>

View File

@@ -94,40 +94,40 @@
<Reference Include="C4IT.F4SD.DisplayFormatting, Version=1.0.9509.21303, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\C4IT.F4SD.DisplayFormatting.1.0.0\lib\netstandard2.0\C4IT.F4SD.DisplayFormatting.dll</HintPath>
</Reference>
<Reference Include="C4IT.F4SD.SupportCaseProtocoll, Version=1.0.9516.21165, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\C4IT.F4SD.SupportCaseProtocoll.1.0.0\lib\netstandard2.0\C4IT.F4SD.SupportCaseProtocoll.dll</HintPath>
<Reference Include="C4IT.F4SD.SupportCaseProtocoll, Version=1.0.9558.28081, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\C4IT.F4SD.SupportCaseProtocoll.1.0.1\lib\netstandard2.0\C4IT.F4SD.SupportCaseProtocoll.dll</HintPath>
</Reference>
<Reference Include="MaterialIcons, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MaterialIcons.1.0.3\lib\MaterialIcons.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=10.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.10.0.2\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=10.0.0.3, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.10.0.3\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=10.0.0.2, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.10.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=10.0.0.3, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.10.0.3\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=10.0.0.2, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.10.0.2\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=10.0.0.3, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.10.0.3\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.WebView2.Core, Version=1.0.3650.58, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.3650.58\lib\net462\Microsoft.Web.WebView2.Core.dll</HintPath>
<Reference Include="Microsoft.Web.WebView2.Core, Version=1.0.3800.47, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.3800.47\lib\net462\Microsoft.Web.WebView2.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.WebView2.WinForms, Version=1.0.3650.58, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.3650.58\lib\net462\Microsoft.Web.WebView2.WinForms.dll</HintPath>
<Reference Include="Microsoft.Web.WebView2.WinForms, Version=1.0.3800.47, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.3800.47\lib\net462\Microsoft.Web.WebView2.WinForms.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.WebView2.Wpf, Version=1.0.3650.58, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.3650.58\lib\net462\Microsoft.Web.WebView2.Wpf.dll</HintPath>
<Reference Include="Microsoft.Web.WebView2.Wpf, Version=1.0.3800.47, Culture=neutral, PublicKeyToken=2a8ab48044d2601e, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.WebView2.1.0.3800.47\lib\net462\Microsoft.Web.WebView2.Wpf.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=10.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.10.0.2\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
<Reference Include="System.Diagnostics.DiagnosticSource, Version=10.0.0.3, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.10.0.3\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
@@ -177,7 +177,12 @@
</Compile>
<Compile Include="AppStartUp.cs" />
<Compile Include="Basics\Browser.cs" />
<Compile Include="Basics\Converter\LanguageCultureConverter.cs" />
<Compile Include="Basics\CustomEvents\HeadingDataEventArgs.cs" />
<Compile Include="Basics\Models\DTOs\MenuDataBaseDto.cs" />
<Compile Include="Basics\Services\Models\CockpitValueDisplayData.cs" />
<Compile Include="Basics\Helper\ActionDisplayTypeInspector.cs" />
<Compile Include="Basics\Services\RemoteDesktop\AgentRemoteDesktopService.cs" />
<Compile Include="Basics\Services\SupportCase\Controllers\SupportCaseController.cs" />
<Compile Include="Basics\Services\SupportCase\Controllers\SupportCaseHeadingController.cs" />
<Compile Include="Basics\ExternalToolExecutorEnh.cs" />
@@ -209,12 +214,15 @@
<Compile Include="Basics\CustomEvents\RelationEventArgs.cs" />
<Compile Include="Basics\Services\RelationService\StagedSearchResultRelationsEventArgs.cs" />
<Compile Include="Basics\Services\SupportCaseSearchService\SupportCaseSearchService.cs" />
<Compile Include="Basics\Services\SupportCase\Controllers\MenuDataFactory.cs" />
<Compile Include="Basics\Services\SupportCase\ISupportCase.cs" />
<Compile Include="Basics\Services\SupportCase\Processors\ISupportCaseProcessor.cs" />
<Compile Include="Basics\Services\SupportCase\SupportCase.cs" />
<Compile Include="Basics\CustomEvents\SupportCaseDataEventArgs.cs" />
<Compile Include="Basics\Services\SupportCase\Processors\SupportCaseDetailsValueProcessesor.cs" />
<Compile Include="Basics\Services\SupportCase\SupportCaseFactory.cs" />
<Compile Include="Basics\Services\SupportCase\SupportCaseProcessor.cs" />
<Compile Include="Basics\Services\SupportCase\SupportCaseProcessorFactory.cs" />
<Compile Include="Basics\Services\SupportCase\Processors\SupportCaseProcessor.cs" />
<Compile Include="Basics\Services\SupportCase\Processors\SupportCaseProcessorFactory.cs" />
<Compile Include="Basics\SupportCaseDataProvider.cs" />
<Compile Include="Basics\Enums\enumActionDisplayType.cs" />
<Compile Include="Basics\Helper\DirectConnectionHelper.cs" />
@@ -244,6 +252,7 @@
<Compile Include="Basics\PrivateSecurePassword.cs" />
<Compile Include="Basics\UiActions\ChangeHealthCardAction.cs" />
<Compile Include="Basics\UiActions\CopyQuickActionProtocolAction.cs" />
<Compile Include="Basics\UiActions\NativeActions\RemoteConnectionAction.cs" />
<Compile Include="Basics\UiActions\UiCopyDetailsTableContent.cs" />
<Compile Include="Basics\UiActions\UiDummyQuickAction.cs" />
<Compile Include="Basics\Models\DataHistoryValueModel.cs" />
@@ -252,6 +261,7 @@
<Compile Include="Basics\Models\NamedParameterEntry.cs" />
<Compile Include="Basics\Models\WidgetValueModel.cs" />
<Compile Include="Basics\UiActions\UiDemoQuickAction.cs" />
<Compile Include="Basics\UiActions\UiNativeQuickAction.cs" />
<Compile Include="Basics\UiActions\UiProcessSearchHistoryEntry.cs" />
<Compile Include="Basics\UiActions\UiProcessSearchResultAction.cs" />
<Compile Include="Basics\UiActions\ShowCustomDialog.cs" />
@@ -281,6 +291,18 @@
<Compile Include="Basics\UserControls\ComboBoxPageAble.xaml.cs">
<DependentUpon>ComboBoxPageAble.xaml</DependentUpon>
</Compile>
<Compile Include="Basics\UserControls\CustomMenuItemToolTipTemplate.xaml.cs">
<DependentUpon>CustomMenuItemToolTipTemplate.xaml</DependentUpon>
</Compile>
<Compile Include="Basics\UserControls\Gamification\LevelTracker.xaml.cs">
<DependentUpon>LevelTracker.xaml</DependentUpon>
</Compile>
<Compile Include="Basics\UserControls\FooterButton.xaml.cs">
<DependentUpon>FooterButton.xaml</DependentUpon>
</Compile>
<Compile Include="Basics\UserControls\InformationClassSearchBar.xaml.cs">
<DependentUpon>InformationClassSearchBar.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\DesktopWidgetPage\DesktopWidgetPageView.xaml.cs">
<DependentUpon>DesktopWidgetPageView.xaml</DependentUpon>
</Compile>
@@ -383,6 +405,9 @@
<DependentUpon>CustomMessageBox.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\CustomPopupBase.cs" />
<Compile Include="Pages\LevelUpPage\LevelUpPage.xaml.cs">
<DependentUpon>LevelUpPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\RawHealthCardValuesPage\RawHealthCardValuesPage.xaml.cs">
<DependentUpon>RawHealthCardValuesPage.xaml</DependentUpon>
</Compile>
@@ -501,10 +526,26 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Basics\UserControls\CustomMenuItemToolTipTemplate.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Basics\UserControls\FooterButton.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Basics\UserControls\InformationClassSearchBar.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\DesktopWidgetPage\DesktopWidgetPageView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Basics\UserControls\Gamification\LevelTracker.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Basics\UserControls\HierarchicalSelectionControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -751,6 +792,10 @@
<Compile Include="Basics\UserControls\FunctionMarker.xaml.cs">
<DependentUpon>FunctionMarker.xaml</DependentUpon>
</Compile>
<Page Include="Pages\LevelUpPage\LevelUpPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\M42AuthenticationPage\F4sdM42FormsAuthentication.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -971,6 +1016,10 @@
<Project>{bab63a6a-1524-435d-9f96-7a30b6ee0624}</Project>
<Name>F4SD-AdaptableIcon</Name>
</ProjectReference>
<ProjectReference Include="..\F4SD-Gamification\F4SD-Gamification.csproj">
<Project>{b59e7dfd-81c8-4d98-ace5-a8f1fc51f7a8}</Project>
<Name>F4SD-Gamification</Name>
</ProjectReference>
<ProjectReference Include="..\F4SD-Logging\F4SD-Logging.csproj">
<Project>{7793f281-b226-4e20-b6f6-5d53d70f1dc1}</Project>
<Name>F4SD-Logging</Name>
@@ -1058,11 +1107,21 @@ taskkill -im "F4SD-Cockpit-Client.exe" -f -FI "STATUS eq RUNNING"
<PropertyGroup>
<PreBuildEvent>copy "$(ProjectDir)..\..\C4IT FASD\_Common\XmlSchemas\LanguageDefinitions.xsd" "$(ProjectDir)Config"</PreBuildEvent>
</PropertyGroup>
<Import Project="..\packages\Microsoft.Web.WebView2.1.0.3650.58\build\Microsoft.Web.WebView2.targets" Condition="Exists('..\packages\Microsoft.Web.WebView2.1.0.3650.58\build\Microsoft.Web.WebView2.targets')" />
<Import Project="..\packages\Microsoft.Web.WebView2.1.0.3800.47\build\Microsoft.Web.WebView2.targets" Condition="Exists('..\packages\Microsoft.Web.WebView2.1.0.3800.47\build\Microsoft.Web.WebView2.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Web.WebView2.1.0.3650.58\build\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Web.WebView2.1.0.3650.58\build\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\packages\Microsoft.Web.WebView2.1.0.3800.47\build\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Web.WebView2.1.0.3800.47\build\Microsoft.Web.WebView2.targets'))" />
</Target>
</Project>
<Target Name="CopyPhoenixViewer" AfterTargets="Build">
<ItemGroup>
<PhoenixFiles Include="$(SolutionDir)PhoenixViewer\*" />
</ItemGroup>
<MakeDir Directories="$(TargetDir)Phoenix" />
<Copy
SourceFiles="@(PhoenixFiles)"
DestinationFolder="$(TargetDir)Phoenix"
SkipUnchangedFiles="true" />
</Target>
</Project>

View File

@@ -28,15 +28,15 @@
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<buc:SearchBar x:Name="SearchBarUc"
x:FieldModifier="private"
Grid.Row="0"
FontSize="20"
HorizontalAlignment="Center"
Width="450"
Margin="0 200 0 0"
SearchButtonSize="30"
CloseButtonSize="30" />
<buc:InformationClassSearchBar x:Name="SearchBarUc"
x:FieldModifier="private"
Grid.Row="0"
FontSize="20"
HorizontalAlignment="Center"
Width="450"
Margin="0 200 0 0"
SearchButtonSize="30"
CloseButtonSize="30" />
<buc:SearchFilterBar x:Name="SearchFilterBar"
x:FieldModifier="private"

View File

@@ -24,7 +24,7 @@ using System.Windows.Threading;
using FasdDesktopUi.Basics.Services.SupportCaseSearchService;
using FasdDesktopUi.Basics.Services.RelationService;
using static C4IT.Logging.cLogManager;
using static FasdDesktopUi.Basics.UserControls.SearchBar;
using static FasdDesktopUi.Basics.UserControls.InformationClassSearchBar;
namespace FasdDesktopUi.Pages.AdvancedSearchPage
@@ -39,7 +39,7 @@ namespace FasdDesktopUi.Pages.AdvancedSearchPage
// 3. When F4SD Tray-Icon is clicked, open the new advanced search page
SearchBar.ChangedSearchValueDelegate ChangedSearchValue { get; set; }
InformationClassSearchBar.ChangedSearchValueDelegate ChangedSearchValue { get; set; }
private cF4sdApiSearchResultRelation preSelectedRelation = null;
private static readonly object _currentSearchTaskLock = new object();

View File

@@ -194,16 +194,16 @@ namespace FasdDesktopUi.Pages.CustomMessageBox
return null;
}
public static int Show(string Message, List<string> MultiButtonText, string Caption = null, enumHealthCardStateLevel Level = enumHealthCardStateLevel.None, Window Owner = null, bool TopMost = false, bool CenterScreen = false, int MaxWidth = -1)
{
var messageBox = InitializeMessageBox(Message, Caption, Level, Owner, false, false, MultiButtonText, TopMost, CenterScreen);
if (messageBox == null)
return -1;
if (MaxWidth > 0)
messageBox.MaxWidth = MaxWidth;
messageBox.ShowDialog();
return messageBox.ResultIndex;
}
public static int Show(string Message, List<string> MultiButtonText, string Caption = null, enumHealthCardStateLevel Level = enumHealthCardStateLevel.None, Window Owner = null, bool TopMost = false, bool CenterScreen = false, int MaxWidth = -1)
{
var messageBox = InitializeMessageBox(Message, Caption, Level, Owner, false, false, MultiButtonText, TopMost, CenterScreen);
if (messageBox == null)
return -1;
if (MaxWidth > 0)
messageBox.MaxWidth = MaxWidth;
messageBox.ShowDialog();
return messageBox.ResultIndex;
}
public static bool? Show(string Message, string Caption = null, enumHealthCardStateLevel Level = enumHealthCardStateLevel.None, Window Owner = null, bool HasYesNoButtons = false, bool HasYesNoText = false, bool TopMost = false, bool CenterScreen = false)
{

View File

@@ -8,6 +8,7 @@
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:uc="clr-namespace:FasdDesktopUi.Pages.DetailsPage.UserControls"
xmlns:buc="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:bucg="clr-namespace:FasdDesktopUi.Basics.UserControls.Gamification"
xmlns:quc="clr-namespace:FasdDesktopUi.Basics.UserControls.QuickTip"
xmlns:vm="clr-namespace:FasdDesktopUi.Pages.DetailsPage.ViewModels"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
@@ -84,93 +85,99 @@
Grid.Row="0"
Panel.ZIndex="2"
PreviewMouseLeftButtonDown="Header_PreviewMouseLeftButtonDown">
<DockPanel LastChildFill="False"
Margin="0,-7,0,0">
<Grid>
<DockPanel LastChildFill="False"
Margin="0,-7,0,0">
<Border x:Name="DialogCloseElement"
x:FieldModifier="private"
DockPanel.Dock="Bottom"
HorizontalAlignment="Right"
Cursor="Hand"
CornerRadius="5"
Margin="0 2.5 7.5 -30"
Padding="10 2.5"
Background="{DynamicResource BackgroundColor.DetailsPage.Widget.Value}"
MouseLeftButtonUp="CloseCaseWithTicketIcon_MouseLeftButtonUp"
TouchDown="CloseCaseWithTicketIcon_TouchDown">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ico:AdaptableIcon x:Name="CloseCaseWithTicketIcon"
x:FieldModifier="private"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="0 0 5 0"
Panel.ZIndex="2"
BorderPadding="0"
IconHeight="25"
IconWidth="25"
SelectedMaterialIcon="ic_mail">
<ico:AdaptableIcon.Resources>
<Style TargetType="ico:AdaptableIcon">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource FontColor.Menu.Categories}" />
<Border x:Name="DialogCloseElement"
x:FieldModifier="private"
DockPanel.Dock="Bottom"
HorizontalAlignment="Right"
Cursor="Hand"
CornerRadius="5"
Margin="0 2.5 7.5 -30"
Padding="10 2.5"
Background="{DynamicResource BackgroundColor.DetailsPage.Widget.Value}"
MouseLeftButtonUp="CloseCaseWithTicketIcon_MouseLeftButtonUp"
TouchDown="CloseCaseWithTicketIcon_TouchDown">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ico:AdaptableIcon x:Name="CloseCaseWithTicketIcon"
x:FieldModifier="private"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="0 0 5 0"
Panel.ZIndex="2"
BorderPadding="0"
IconHeight="25"
IconWidth="25"
SelectedMaterialIcon="ic_mail">
<ico:AdaptableIcon.Resources>
<Style TargetType="ico:AdaptableIcon">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource FontColor.Menu.Categories}" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource FontColor.Menu.Categories.Hover}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ico:AdaptableIcon.Resources>
</ico:AdaptableIcon>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource FontColor.Menu.Categories.Hover}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ico:AdaptableIcon.Resources>
</ico:AdaptableIcon>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase}">
<TextBlock.Resources>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="FontSize"
Value="16" />
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories}" />
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase}">
<TextBlock.Resources>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="FontSize"
Value="16" />
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories}" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories.Hover}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Resources>
</TextBlock>
</StackPanel>
</Border>
<StackPanel DockPanel.Dock="Right"
Orientation="Horizontal"
HorizontalAlignment="Right">
<Border x:Name="ZoomValueBorder"
Grid.Row="1"
Margin="0 10 10 0"
Opacity="0"
CornerRadius="7.5"
Padding="10 5"
Background="{DynamicResource Color.SoftContrast}">
<TextBlock x:Name="ZoomValueTextBlock"
Foreground="{DynamicResource FontColor.DetailsPage.DataHistory.Value}"
FontWeight="Bold"
FontSize="20" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories.Hover}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Resources>
</TextBlock>
</StackPanel>
</Border>
<uc:DetailsPageWindowStateBar x:Name="WindowStateBarUserControl" />
</StackPanel>
<StackPanel DockPanel.Dock="Right"
Orientation="Horizontal"
HorizontalAlignment="Right">
</DockPanel>
<Border x:Name="ZoomValueBorder"
Grid.Row="1"
Margin="0 10 10 0"
Opacity="0"
CornerRadius="7.5"
Padding="10 5"
Background="{DynamicResource Color.SoftContrast}">
<TextBlock x:Name="ZoomValueTextBlock"
Foreground="{DynamicResource FontColor.DetailsPage.DataHistory.Value}"
FontWeight="Bold"
FontSize="20" />
</Border>
<uc:DetailsPageWindowStateBar x:Name="WindowStateBarUserControl" />
</StackPanel>
</DockPanel>
<bucg:LevelTracker x:Name="LevelTrackerUc"
DockPanel.Dock="Top"
HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
</Grid>
</Border>
<Border x:Name="Body"
@@ -214,7 +221,7 @@
VerticalAlignment="Top"
HorizontalAlignment="Left"
Grid.RowSpan="3"
Panel.ZIndex="1"/>
Panel.ZIndex="1" />
<uc:DetailsPageWidgetCollection x:Name="WidgetCollection"
Grid.Row="1"
@@ -235,7 +242,8 @@
MaxWidth="300"
MinWidth="280"
VerticalAlignment="Top"
IsVisibleChanged="DynamicElement_IsVisibleChanged" />
IsVisibleChanged="DynamicElement_IsVisibleChanged"
SearchValueChanged="QuickActionSelectorUc_SearchValueChanged" />
<DockPanel LastChildFill="True">
@@ -246,13 +254,6 @@
Visibility="Collapsed"
IsVisibleChanged="DynamicElement_IsVisibleChanged" />
<Decorator x:Name="NotepadDecorator"
DockPanel.Dock="Right"
MaxWidth="400"
Margin="19 27.5 0 0"
Visibility="Visible"
IsVisibleChanged="DynamicElement_IsVisibleChanged" />
<Decorator x:Name="QuickTipDecorator"
DockPanel.Dock="Right"
MaxWidth="400"
@@ -265,6 +266,13 @@
</Decorator>
<Decorator x:Name="NotepadDecorator"
DockPanel.Dock="Right"
MaxWidth="400"
Margin="19 27.5 0 0"
Visibility="Visible"
IsVisibleChanged="DynamicElement_IsVisibleChanged" />
<uc:DetailsPageDataHistoryCollection x:Name="DataHistoryCollectionUserControl"
DockPanel.Dock="Left"
HorizontalAlignment="Left"
@@ -307,10 +315,16 @@
<buc:MenuBar x:Name="MenuBarUserControl"
x:FieldModifier="private"
MenuBarItemData="{Binding MenuBarData}" />
<buc:SearchBar x:Name="SearchBarUserControl"
x:FieldModifier="private"
Visibility="Collapsed"
HorizontalAlignment="Right" />
<buc:InformationClassSearchBar x:Name="SearchBarUserControl"
x:FieldModifier="private"
Visibility="Collapsed"
HorizontalAlignment="Right" />
<buc:FooterButton x:Name="FooterBtn"
x:FieldModifier="private"
Visibility="Collapsed"
VerticalAlignment="Bottom"
HorizontalAlignment="Center" />
<StackPanel x:Name="IconTimerPanel"
Orientation="Horizontal"
@@ -327,7 +341,6 @@
VerticalAlignment="Bottom"
Margin="15 -2.5"
OnPauseStarted="CaseTimer_OnPauseStarted" />
</StackPanel>
</Grid>
</Border>

View File

@@ -1,37 +1,37 @@
using System;
using C4IT.FASD.Base;
using C4IT.FASD.Cockpit.Communication;
using C4IT.MultiLanguage;
using FasdDesktopUi.Basics;
using FasdDesktopUi.Basics.Converter;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.SupportCase.Controllers;
using FasdDesktopUi.Basics.UiActions;
using FasdDesktopUi.Basics.UserControls;
using FasdDesktopUi.Basics.UserControls.QuickTip;
using FasdDesktopUi.Pages.DetailsPage.Models;
using FasdDesktopUi.Pages.DetailsPage.UserControls;
using FasdDesktopUi.Pages.DetailsPage.ViewModels;
using FasdDesktopUi.Pages.SettingsPage;
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.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media.Effects;
using System.Windows.Controls;
using System.Threading.Tasks;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Shell;
using FasdDesktopUi.Basics;
using FasdDesktopUi.Basics.UiActions;
using FasdDesktopUi.Basics.UserControls;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Pages.SettingsPage;
using FasdDesktopUi.Pages.DetailsPage.Models;
using FasdDesktopUi.Pages.DetailsPage.ViewModels;
using FasdDesktopUi.Pages.DetailsPage.UserControls;
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using System.Windows.Threading;
using static C4IT.Logging.cLogManager;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Converter;
using FasdDesktopUi.Basics.Services.SupportCase.Controllers;
using static System.Windows.Forms.AxHost;
namespace FasdDesktopUi.Pages.DetailsPage
{
@@ -107,7 +107,7 @@ namespace FasdDesktopUi.Pages.DetailsPage
case SettingsPageBase _:
case CustomMessageBox.CustomMessageBox _:
case TicketCompletion.TicketCompletion _:
case SearchBar _:
case InformationClassSearchBar _:
case SuccessPage.SuccessPage _:
case BlurInvokerContainer _:
return true;
@@ -201,8 +201,8 @@ namespace FasdDesktopUi.Pages.DetailsPage
}
private void HandleAvailableRelationsAdded(object sender, RelationEventArgs e)
{
}
=> Dispatcher.Invoke(() => NavigationHeadingUc.HeadingData = _supportCaseController.GetHeadingData().ToList());
private void HandleFocusedRelationsChanged(object sender, RelationEventArgs e)
{
@@ -234,15 +234,15 @@ namespace FasdDesktopUi.Pages.DetailsPage
isDataChangedEventRunning = true;
Dispatcher.Invoke(() =>
Dispatcher.Invoke(async () =>
{
if (QuickActionDecorator.Child is DataCanvas dataCanvas)
Dispatcher.Invoke(async () => await dataCanvas.UpdateDataAsync());
_ = Dispatcher.Invoke(async () => await dataCanvas.UpdateDataAsync());
if (WidgetCollection.WidgetDataList is null || WidgetCollection.WidgetDataList.Count == 0)
WidgetCollection.WidgetDataList = _supportCaseController?.GetWidgetData();
WidgetCollection.WidgetDataList = _supportCaseController?.GetWidgetsData();
WidgetCollection.UpdateWidgetData(_supportCaseController?.GetWidgetData());
WidgetCollection.UpdateWidgetData(_supportCaseController?.GetWidgetsData());
if (DataHistoryCollectionUserControl.HistoryDataList is null || DataHistoryCollectionUserControl.HistoryDataList.Count == 0)
DataHistoryCollectionUserControl.HistoryDataList = _supportCaseController?.GetHistoryData();
@@ -255,7 +255,9 @@ namespace FasdDesktopUi.Pages.DetailsPage
CustomizableSectionUc.UpdateContainerCollection(_supportCaseController?.GetContainerData());
if (this.DataContext is DetailsPageViewModel viewModel)
viewModel.MenuBarData = _supportCaseController?.GetMenuBarData();
viewModel.MenuBarData = _supportCaseController?.GetMenuData().ToList();
UpdateQuickActionSelectorVisibility();
if (_lastDesiredHeightOfWidgetCollection != WidgetCollection.DesiredSize.Height)
{
@@ -263,6 +265,10 @@ namespace FasdDesktopUi.Pages.DetailsPage
MainGrid.InvalidateMeasure();
MainGrid.UpdateLayout();
}
var footerMenuData = _supportCaseController.GetMenuData().FirstOrDefault(data => data.UiAction is UiNativeQuickAction);
FooterBtn.QuickAction = footerMenuData?.UiAction as cUiQuickAction;
FooterBtn.LabelText = footerMenuData?.MenuText;
});
if (shouldReRunDataChangedEvent)
@@ -275,6 +281,41 @@ namespace FasdDesktopUi.Pages.DetailsPage
}
}
private void UpdateQuickActionSelectorVisibility()
{
try
{
cHealthCard selectedHealthcard = _supportCaseController.SupportCaseDataProviderArtifact.HealthCardDataHelper.SelectedHealthCard;
bool showHistorySection = selectedHealthcard.CategoriesHistory?.StateCategories != null && selectedHealthcard.CategoriesHistory.StateCategories.Count > 0;
if (showHistorySection && cFasdCockpitConfig.Instance.IsHistoryQuickActionSelectorVisible)
{
QuickActionSelectorUc.IsLocked = cFasdCockpitConfig.Instance.IsHistoryQuickActionSelectorVisible;
MoreButtonClickedAction();
}
else if (!showHistorySection && cFasdCockpitConfig.Instance.IsCustomizableQuickActionSelectorVisible)
{
var ticketMenuData = _supportCaseController.GetMenuData().FirstOrDefault(menuData => menuData.MenuText == "Ticket");
if (ticketMenuData != null)
if (ticketMenuData is cMenuDataContainer containerMenuData)
{
QuickActionSelectorUc.QuickActionSelectorHeading = containerMenuData.MenuText;
QuickActionSelectorUc.QuickActionList = containerMenuData.SubMenuData;
}
QuickActionSelectorUc.IsLocked = cFasdCockpitConfig.Instance.IsCustomizableQuickActionSelectorVisible;
if (cFasdCockpitConfig.Instance.IsCustomizableQuickActionSelectorVisible)
QuickActionSelectorUc.Visibility = Visibility.Visible;
}
}
catch (Exception ex)
{
LogException(ex);
}
}
/// <summary>
/// Sets the visibility of History and Customizable Section based on the currently selected Healthcard.
/// </summary>
@@ -597,6 +638,7 @@ namespace FasdDesktopUi.Pages.DetailsPage
// define drawing area
UIElement drawingArea = this;
switch (e.UiAction)
{
case cChangeHealthCardAction _:
@@ -604,6 +646,11 @@ namespace FasdDesktopUi.Pages.DetailsPage
case UiShowRawHealthcardValues _:
break;
case cUiQuickAction _:
if (!(e.OriginalSource is QuickTipStep) && QuickTipStatusMonitorUc.IsVisible && !QuickTipStatusMonitorUc.TryCancelQuickTip())
return;
drawingArea = QuickActionDecorator;
ToggleHorizontalCollapse(true, true);
break;
case cShowRecommendationAction _:
case cShowDetailedDataAction _:
drawingArea = QuickActionDecorator;
@@ -678,7 +725,7 @@ namespace FasdDesktopUi.Pages.DetailsPage
{
IconTimerPanel.HorizontalAlignment = HorizontalAlignment.Right;
IconTimerPanel.Children.Remove(F4SDIcon);
IconTimerPanel.Children.Insert(1, F4SDIcon);
IconTimerPanel.Children.Insert(IconTimerPanel.Children.Count, F4SDIcon);
}
else
{
@@ -687,6 +734,7 @@ namespace FasdDesktopUi.Pages.DetailsPage
IconTimerPanel.Children.Insert(0, F4SDIcon);
}
FooterBtn.HorizontalAlignment = cFasdCockpitConfig.Instance.Global.FavouriteBarAlignment == enumF4sdHorizontalAlignment.Center ? HorizontalAlignment.Right : HorizontalAlignment.Center;
MenuBarUserControl.HorizontalAlignment = InternalEnumConverter.GetHorizontalAlignment(cFasdCockpitConfig.Instance.Global.FavouriteBarAlignment);
}
catch (Exception E)
@@ -699,6 +747,7 @@ namespace FasdDesktopUi.Pages.DetailsPage
{
UpdateHistoryWidth();
UpdateFooterPositions();
LevelTrackerUc.Visibility = cFasdCockpitConfig.Instance.Global.UseGamification ? Visibility.Visible : Visibility.Collapsed;
}
private void ApiConnectionStatusChanged(cConnectionStatusHelper.enumOnlineStatus? Status)
@@ -923,13 +972,27 @@ namespace FasdDesktopUi.Pages.DetailsPage
break;
}
return;
}
// Close Quick Action Section
if (e.Key == Key.Escape && QuickActionSelectorUc.Visibility == Visibility.Visible)
{
CloseQuickActionSelector();
return;
}
if (FocusManager.GetFocusedElement(this) is TextBox)
return;
bool isTextInputFocused = FocusManager.GetFocusedElement(this) is TextBox || FocusManager.GetFocusedElement(this) is RichTextBox;
if (FocusManager.GetFocusedElement(this) is RichTextBox)
// Open Quick Action Section
if (e.Key == Key.Q && !isTextInputFocused)
{
MoreButtonClickedAction();
e.Handled = true;
return;
}
if (isTextInputFocused)
return;
List<DetailsPageDataHistorySection> unpinnedDataHistories = DataHistoryCollectionUserControl.HistorySectionControls.Where(x => !x.IsVerticalExpandLocked).ToList();
@@ -970,9 +1033,6 @@ namespace FasdDesktopUi.Pages.DetailsPage
if (Keyboard.Modifiers == ModifierKeys.Control)
SearchButtonClickedAction();
break;
case Key.Q:
MoreButtonClickedAction();
break;
case Key.NumPad0:
case Key.D0:
if (Keyboard.Modifiers != ModifierKeys.Control)
@@ -1177,8 +1237,6 @@ namespace FasdDesktopUi.Pages.DetailsPage
{
tempSubMenuList.Add(new cMenuDataBase(copyTemplate.Value));
}
tempMoreQuickActionList.Insert(0, new cMenuDataContainer() { MenuText = cMultiLanguageSupport.GetItem("QuickAction.CopyContent"), MenuIcon = new F4SD_AdaptableIcon.IconData(enumInternIcons.menuBar_copy), UiAction = new cSubMenuAction(true) { Name = cMultiLanguageSupport.GetItem("QuickAction.CopyContent"), SubMenuData = tempSubMenuList }, SubMenuData = tempSubMenuList });
}
QuickActionSelectorUc.QuickActionList = tempMoreQuickActionList;
@@ -1187,6 +1245,10 @@ namespace FasdDesktopUi.Pages.DetailsPage
ToggleHorizontalCollapse(true);
QuickActionSelectorUc.Visibility = Visibility.Visible;
QuickActionSelectorUc.CloseButtonClickedAction = BlurBorder_Click;
QuickActionSelectorUc.Search.ActivateManualSearch();
QuickActionSelectorUc.Search.FocusInput();
QuickActionSelectorUc.Search.Clear();
}
catch (Exception E)
{
@@ -1256,6 +1318,7 @@ namespace FasdDesktopUi.Pages.DetailsPage
notepad.Visibility = Visibility.Collapsed;
NotepadVisibility = false;
ResetWindowFocus();
ChangeNotepadNotification();
}
else
@@ -1451,6 +1514,29 @@ namespace FasdDesktopUi.Pages.DetailsPage
ReinitializeNotepad();
DataHistoryCollectionUserControl.ToggleVerticalCollapseDetails(true);
UpdateHistoryWidth();
Task.Run(async () =>
{
if (await cFasdCockpitCommunicationBase.Instance.RemoteDesktopManager.IsRemoteDesktopCommunicationAvailable())
Dispatcher.Invoke(() => FooterBtn.Visibility = Visibility.Visible);
});
}
catch (Exception E)
{
LogException(E);
}
}
private void ResetWindowFocus()
{
try
{
Window window = Window.GetWindow(this);
if (window == null)
return;
FocusManager.SetFocusedElement(window, window);
Keyboard.Focus(window);
}
catch (Exception E)
{
@@ -1701,5 +1787,30 @@ namespace FasdDesktopUi.Pages.DetailsPage
QuickActionDecorator.Visibility = Visibility.Collapsed;
}
private void QuickActionSelectorUc_SearchValueChanged(object sender, string e)
{
if (string.IsNullOrWhiteSpace(e))
{
QuickActionSelectorUc.QuickActionList = _supportCaseController.GetMenuData().ToList();
QuickActionSelectorUc.QuickActionSelectorHeading = "Quick Actions";
return;
}
QuickActionSelectorUc.QuickActionList = _supportCaseController.GetFilteredMenuData(new MenuDataFilter(e)).ToList();
}
private void CloseQuickActionSelector()
{
try
{
QuickActionSelectorUc.CloseButton_Click();
QuickActionSelectorUc.Search.Clear();
}
catch (Exception E)
{
LogException(E);
}
}
}
}

View File

@@ -72,7 +72,7 @@ namespace FasdDesktopUi.Pages.DetailsPage.UserControls
var updatedColumnValues = (DetailsPageDataHistoryColumnModel)e.NewValue;
_me.UpdateColumnSize(updatedColumnValues.ColumnValues.Count - _me.MainGrid.RowDefinitions.Count);
_me.RefreshColumnHeader(updatedColumnValues.Content);
_me.ColumnHeaderTextBlock.Text = updatedColumnValues.Content;
_me.RefreshColumnStatusIcon(updatedColumnValues.HighlightColor);
_me.RefreshValueSection(updatedColumnValues);
}
@@ -155,7 +155,8 @@ namespace FasdDesktopUi.Pages.DetailsPage.UserControls
border.ClearValue(TagProperty);
border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder");
break;
};
}
;
border.Tag = valueInfo?.ThresholdValues;
}
@@ -163,7 +164,7 @@ namespace FasdDesktopUi.Pages.DetailsPage.UserControls
{
LogException(E);
}
}
#region Initialize Controls
@@ -276,22 +277,6 @@ namespace FasdDesktopUi.Pages.DetailsPage.UserControls
#region Refresh Values
private void RefreshColumnHeader(string columnHeader)
{
string headerContent;
if (int.TryParse(columnHeader, out int dayIndex))
{
CultureInfo culture = new CultureInfo(cMultiLanguageSupport.CurrentLanguage);
string customDateFormat = cMultiLanguageSupport.GetItem("Global.Date.Format.ShortDateWithDay", "ddd. dd.MM.");
headerContent = dayIndex == 0 ? cMultiLanguageSupport.GetItem("Global.Date.Today", DateTime.Now.ToString(customDateFormat, culture)) : DateTime.Today.AddDays(-dayIndex).ToString(customDateFormat, culture);
}
else
headerContent = columnHeader;
ColumnHeaderTextBlock.Text = headerContent;
}
private void RefreshColumnStatusIcon(enumHighlightColor? statusColor)
{
ColumnStatusIcon.IconWidth = 25;
@@ -386,7 +371,7 @@ namespace FasdDesktopUi.Pages.DetailsPage.UserControls
default:
valueRowTextBlock.SetResourceReference(ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value");
break;
};
}
valueRow.Visibility = Visibility.Visible;
valueRow.Opacity = 1;

View File

@@ -18,7 +18,6 @@ using C4IT.MultiLanguage;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using C4IT.FASD.Cockpit.Communication;
using FasdDesktopUi.Basics.Services.SupportCase.Controllers;
namespace FasdDesktopUi.Pages.DetailsPage.UserControls
@@ -37,7 +36,7 @@ namespace FasdDesktopUi.Pages.DetailsPage.UserControls
if (value != null)
{
UpdateHeaderHighlights();
SetHeadingVisibility();
_ = SetHeadingVisibilityAsync();
}
}
}
@@ -110,7 +109,7 @@ namespace FasdDesktopUi.Pages.DetailsPage.UserControls
}
}
private async Task SetHeadingVisibility()
private async Task SetHeadingVisibilityAsync()
{
try
{
@@ -667,19 +666,17 @@ namespace FasdDesktopUi.Pages.DetailsPage.UserControls
List<cMenuDataBase> quickActionList = new List<cMenuDataBase>();
if (dataProvider.CaseRelations != null && dataProvider.CaseRelations.TryGetValue(swapCaseData.SelectedCaseInformationClass, out var storedRelations))
foreach (var storedRelation in SupportCaseController.GetRelationsOf(swapCaseData.SelectedCaseInformationClass))
{
foreach (var storedRelation in storedRelations)
bool isMatchingRelation = IsMatchingRelation(storedRelation, swapCaseData.HeadingDatas);
quickActionList.Add(new cMenuDataSearchRelation(storedRelation)
{
bool isMatchingRelation = IsMatchingRelation(storedRelation, swapCaseData.HeadingDatas);
quickActionList.Add(new cMenuDataSearchRelation(storedRelation)
{
IsMatchingRelation = isMatchingRelation,
IsUsedForCaseEnrichment = true,
UiAction = new cChangeHealthCardAction(storedRelation, supportCaseController)
});
}
IsMatchingRelation = isMatchingRelation,
IsUsedForCaseEnrichment = true,
UiAction = new cChangeHealthCardAction(storedRelation, supportCaseController)
});
}
if (quickActionList.Count > 0)
customMenu.MenuDataList = quickActionList;
}

View File

@@ -414,7 +414,7 @@ namespace FasdDesktopUi.Pages.DetailsPage.UserControls
if (Data.UiActionTitle is cShowDetailedDataAction)
functionMarkerEntry.SelectedIcon = enumInternIcons.misc_dot;
else if (Data.UiActionTitle is cUiQuickAction || Data.UiActionTitle is cSubMenuAction)
else if (Data.UiActionTitle is cUiQuickAction || Data.UiActionTitle is cSubMenuAction || Data.UiActionTitle is cUiQuickTipAction)
functionMarkerEntry.SelectedIcon = enumInternIcons.misc_functionBolt;
}
else

View File

@@ -0,0 +1,112 @@
<Window x:Class="FasdDesktopUi.Pages.LevelUpPage.LevelUpPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FasdDesktopUi.Pages.LevelUpPage"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
Title="LevelUpPage"
Height="700"
Width="600"
WindowStartupLocation="CenterScreen"
ResizeMode="NoResize"
WindowStyle="None"
AllowsTransparency="True"
x:Name="LevelUpWindow"
IsVisibleChanged="HandleVisibilityChanged"
Background="Transparent">
<Window.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<Style TargetType="TextBlock">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.DetailsPage.TitleSection.Header}" />
<Setter Property="HorizontalAlignment"
Value="Center" />
<Setter Property="FontWeight"
Value="Bold" />
</Style>
</Window.Resources>
<Border Padding="75"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="{DynamicResource Color.AppBackground}"
CornerRadius="25">
<Border.Effect>
<DropShadowEffect Color="{DynamicResource BorderDarkColor}"
Opacity="0.5"
BlurRadius="25"/>
</Border.Effect>
<StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<TextBlock FontSize="60"
Margin="0 0 5 10"
FontWeight="UltraBold">Level Up!</TextBlock>
<ico:AdaptableIcon SelectedInternGif="partyPopper"
IconHeight="130"
IconWidth="130"
Margin="0 -60 -45 0" />
</StackPanel>
<Border Height="225"
Width="225"
CornerRadius="150"
BorderBrush="{DynamicResource Color.FunctionMarker}"
BorderThickness="35"
Margin="0 0 0 10">
<StackPanel>
<TextBlock x:Name="LastLevelTextBlock"
FontSize="110"
VerticalAlignment="Top">
<TextBlock.RenderTransform>
<TranslateTransform x:Name="UpperTransform" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock x:Name="NewLevelTextBlock"
FontSize="110"
VerticalAlignment="Top"
Margin="0,40,0,0">
<TextBlock.RenderTransform>
<TranslateTransform x:Name="LowerTransform" />
</TextBlock.RenderTransform>
</TextBlock>
</StackPanel>
</Border>
<TextBlock Text="{Binding ElementName=LevelUpWindow, Path=LevelTitle}"
FontSize="40"
FontWeight="Bold" />
<Border HorizontalAlignment="Center"
Padding="15 7.5"
CornerRadius="5"
Margin="0 15 0 0"
Cursor="Hand"
Background="{DynamicResource Color.FunctionMarker}"
MouseLeftButtonUp="Continue_Click"
TouchDown="Continue_Click">
<Border.Resources>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}"
Value="True">
<Setter Property="Opacity"
Value="0.7" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Resources>
<TextBlock FontSize="17"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Gamification.LevelUp.Continue}"
Foreground="{DynamicResource Color.AppBackground}" />
</Border>
</StackPanel>
</Border>
</Window>

View File

@@ -0,0 +1,91 @@
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace FasdDesktopUi.Pages.LevelUpPage
{
public partial class LevelUpPage : Window
{
public int NewLevel
{
get { return (int)GetValue(NewLevelProperty); }
set { SetValue(NewLevelProperty, value); }
}
public static readonly DependencyProperty NewLevelProperty =
DependencyProperty.Register(nameof(NewLevel), typeof(int), typeof(LevelUpPage), new PropertyMetadata(0, new PropertyChangedCallback(HandleLevelChanged)));
private static void HandleLevelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is LevelUpPage levelupPage))
return;
levelupPage.LastLevelTextBlock.Text = (levelupPage.NewLevel - 1).ToString();
levelupPage.NewLevelTextBlock.Text = levelupPage.NewLevel.ToString();
}
public string LevelTitle
{
get { return (string)GetValue(LevelTitleProperty); }
set { SetValue(LevelTitleProperty, value); }
}
public static readonly DependencyProperty LevelTitleProperty =
DependencyProperty.Register(nameof(LevelTitle), typeof(string), typeof(LevelUpPage), new PropertyMetadata("string.Empty"));
public LevelUpPage()
{
InitializeComponent();
}
private async Task AnimateText()
{
await Task.Delay(900);
double animationDistance = NewLevelTextBlock.ActualHeight + NewLevelTextBlock.Margin.Top + NewLevelTextBlock.Margin.Bottom;
Duration duration = TimeSpan.FromMilliseconds(500);
DoubleAnimation lowerAnimation = new DoubleAnimation
{
From = 0,
To = -animationDistance,
Duration = duration,
EasingFunction = new CubicEase
{
EasingMode = EasingMode.EaseInOut
}
};
DoubleAnimation upperAnimation = new DoubleAnimation
{
From = 0,
To = -animationDistance,
Duration = duration,
EasingFunction = new CubicEase
{
EasingMode = EasingMode.EaseInOut
}
};
LowerTransform.BeginAnimation(TranslateTransform.YProperty, lowerAnimation);
UpperTransform.BeginAnimation(TranslateTransform.YProperty, upperAnimation);
}
private async void HandleVisibilityChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (Visibility != Visibility.Visible)
return;
await AnimateText();
}
private void Continue_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
}

View File

@@ -183,12 +183,12 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<buc:SearchBar x:Name="SearchBarUc"
x:FieldModifier="private"
Grid.Row="0"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Width="330" />
<buc:InformationClassSearchBar x:Name="SearchBarUc"
x:FieldModifier="private"
Grid.Row="0"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Width="330" />
</Grid>
</Grid>

View File

@@ -197,8 +197,8 @@ namespace FasdDesktopUi.Pages.SearchPage
cSearchManager.ResolveRelations(searchHistoryEntry.Relations);
ILookup<enumFasdInformationClass, cMenuDataBase> relationsLookup = searchHistoryEntry.Relations
.OrderBy(r => r.UsingLevel)
.ThenBy(r => r.LastUsed)
.OrderBy(r => r.LastUsed)
.ThenBy(r => r.UsingLevel)
.ToLookup(GetInformationClass, r => GetMenuData(r, relationService));
Dispatcher.Invoke(() =>
@@ -799,7 +799,7 @@ namespace FasdDesktopUi.Pages.SearchPage
Dispatcher.Invoke(() =>
{
var first = e.RelatedTo.FirstOrDefault();
var relationSearchResult = new cSearchHistorySearchResultEntry(first.DisplayName, first.DisplayName, e.RelatedTo.ToList(), e.StagedResultRelations.Relations.ToList(), this);
var relationSearchResult = new cSearchHistorySearchResultEntry(first.DisplayName, first.Name, e.RelatedTo.ToList(), e.StagedResultRelations.Relations.ToList(), this, _relationService);
ShowSearchRelations(relationSearchResult, e.RelationService, this);
UpdatePendingInformationClasses(e.StagedResultRelations.PendingInformationClasses);
@@ -1033,7 +1033,7 @@ namespace FasdDesktopUi.Pages.SearchPage
private bool TryOpenTicketOverviewRelationExternally(cF4sdApiSearchResultRelation relation)
{
return TicketDeepLinkHelper.TryOpenTicketRelationExternally(relation);
return TicketExternalLinkHelper.TryOpenTicketRelationExternally(relation);
}
private Task RunTicketSearchAsync(string ticketName, Guid ticketId, string userName, string sids, bool suppressUi = false)
@@ -1461,7 +1461,8 @@ namespace FasdDesktopUi.Pages.SearchPage
header,
new List<cFasdApiSearchResultEntry>(),
relations,
this
this,
_relationService
)
{ isSeen = true };
_ticketOverviewHistoryEntries.Add(entry);
@@ -1695,7 +1696,7 @@ namespace FasdDesktopUi.Pages.SearchPage
if (filteredResults?.PreSelectedRelation != null)
{
List<cFasdApiSearchResultEntry> selectedResult = filteredResults.Results.Values.FirstOrDefault();
var processSearchResult = new cUiProcessSearchResultAction(selectedResult.FirstOrDefault()?.DisplayName, this, selectedResult) { PreSelectedSearchRelation = filteredResults.PreSelectedRelation };
var processSearchResult = new cUiProcessSearchResultAction(selectedResult.FirstOrDefault()?.Name, this, selectedResult) { PreSelectedSearchRelation = filteredResults.PreSelectedRelation };
Dispatcher.Invoke(async () =>
{
bool isSearchOngoing = await processSearchResult.RunUiActionAsync(this, this, false, null);

View File

@@ -103,13 +103,13 @@
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
@@ -604,7 +604,7 @@
<TextBlock Grid.Row="7" Grid.ColumnSpan="3"
x:Name="txtAuthenticationError"
Text="Sie konnten nicht angemeldet werden. Bitte ändern Sie ihre Angaben für eine gültige Anmeldung."
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=M42Settings.AutenticationError}"
Grid.Column="0"
Margin="10 3 0 3"
Foreground="Red"

View File

@@ -348,6 +348,26 @@
</Grid>
<StackPanel x:Name="UseGamificationLabel"
Orientation="Horizontal">
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Menu.UseGamification}" />
<ico:AdaptableIcon x:Name="UseGamifictationPolicy"
SelectedInternIcon="lock_closed"
PrimaryIconColor="{DynamicResource Color.Menu.Icon}"
BorderPadding="0"
Margin="-20 0 0 0"
IconWidth="12"
IconHeight="12"
Visibility="Collapsed" />
</StackPanel>
<CheckBox x:Name="UseGamificationCheckBox"
Style="{DynamicResource ToggleSwitch}"
IsChecked="{Binding ElementName=SettingsWindow, Path=UseGamification}"
HorizontalAlignment="Left"
Margin="0,3,0,10">
</CheckBox>
</StackPanel>
</Border>

View File

@@ -1,34 +1,19 @@
using C4IT.MultiLanguage;
using C4IT.Configuration;
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics;
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UserControls.AdaptableIcon;
using FasdDesktopUi.Pages.DetailsPage;
using FasdDesktopUi.Pages.SlimPage;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using static C4IT.Logging.cLogManager;
using System.Reflection;
using C4IT.Logging;
using System.Windows.Navigation;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics;
using System.Diagnostics;
using C4IT.Configuration;
namespace FasdDesktopUi.Pages.SettingsPage
{
@@ -36,11 +21,10 @@ namespace FasdDesktopUi.Pages.SettingsPage
{
#region Properties
private static SettingsPageView _Instance = null;
public static SettingsPageView Instance { get
{
return _Instance ?? (_Instance = new SettingsPageView());
}
private static SettingsPageView _instance = null;
public static SettingsPageView Instance
{
get { return _instance ?? (_instance = new SettingsPageView()); }
}
private Dictionary<enumHighlightColor, bool> highlightColorActivationStatus;
@@ -104,7 +88,8 @@ namespace FasdDesktopUi.Pages.SettingsPage
public int PositionOfSmallViews
{
get {
get
{
return cF4sdGlobalConfig.ConvertHorizontalAlignmentToPosition(cFasdCockpitConfig.Instance.Global.SmallViewAlignment, 0);
}
set
@@ -152,6 +137,18 @@ namespace FasdDesktopUi.Pages.SettingsPage
}
}
public bool UseGamification
{
get => cFasdCockpitConfig.Instance.Global.UseGamification;
set
{
cFasdCockpitConfig.Instance.Global.UseGamification = value;
cFasdCockpitConfig.Instance.Global.Save(nameof(cFasdCockpitConfig.Instance.Global.UseGamification));
cFasdCockpitConfig.Instance.OnUiSettingsChanged();
OnPropertyChanged(nameof(UseGamification));
}
}
#endregion
public static SettingsPageView Create()
@@ -184,7 +181,7 @@ namespace FasdDesktopUi.Pages.SettingsPage
FavouritePositionRightTextBlock.ClearValue(ForegroundProperty);
FavouritePositionSlider.SetResourceReference(BackgroundProperty, "Color.FunctionMarker");
break;
case 2:
case 2:
FavouritePositionRightTextBlock.SetResourceReference(ForegroundProperty, "Color.FunctionMarker");
FavouritePositionLeftTextBlock.ClearValue(ForegroundProperty);
break;
@@ -233,86 +230,30 @@ namespace FasdDesktopUi.Pages.SettingsPage
ZoomDetailsPageInPecent = cFasdCockpitConfig.Instance.DetailsPageZoom;
ZoomSlimPageInPercent = cFasdCockpitConfig.Instance.SlimPageZoom;
// hide or deactivate ShouldSkipSlimView options due to the policies
var _policy = cFasdCockpitConfig.Instance.Global.GetPropertyPolicy("ShouldSkipSlimView");
if (_policy == enumConfigPolicy.Hidden)
{
ShouldSkipSlimViewLabel.Visibility = Visibility.Collapsed;
ShouldSkipSlimViewCheckBox.Visibility = Visibility.Collapsed;
}
else
{
ShouldSkipSlimViewLabel.Visibility = Visibility.Visible;
ShouldSkipSlimViewCheckBox.Visibility = Visibility.Visible;
}
if (_policy == enumConfigPolicy.Default)
{
ShouldSkipSlimViewCheckBox.IsEnabled = true;
ShouldSkipSlimViewPolicy.Visibility = Visibility.Collapsed;
ShouldSkipSlimViewCheckBox.ToolTip = null;
ShouldSkipSlimViewPolicy.ToolTip = null;
}
else
{
ShouldSkipSlimViewCheckBox.IsEnabled = false;
ShouldSkipSlimViewPolicy.Visibility = Visibility.Visible;
ShouldSkipSlimViewCheckBox.ToolTip = cMultiLanguageSupport.GetItem("Settings.Global.PolicyTooltip");
ShouldSkipSlimViewPolicy.ToolTip = cMultiLanguageSupport.GetItem("Settings.Global.PolicyTooltip");
}
UpdatePolicyElements("ShouldSkipSlimView", ShouldSkipSlimViewLabel, ShouldSkipSlimViewCheckBox, ShouldSkipSlimViewPolicy);
OnPropertyChanged(nameof(ShouldSkipSlimView));
// hide or deactivate SmallViewAlignment options due to the policies
_policy = cFasdCockpitConfig.Instance.Global.GetPropertyPolicy("SmallViewAlignment");
if (_policy == enumConfigPolicy.Hidden)
{
PositionOfSmallViewsLabel.Visibility = Visibility.Collapsed;
PositionOfSmallViewsInput.Visibility = Visibility.Collapsed;
}
else
{
PositionOfSmallViewsLabel.Visibility = Visibility.Visible;
PositionOfSmallViewsInput.Visibility = Visibility.Visible;
}
if (_policy == enumConfigPolicy.Default)
{
PositionOfSmallViewsInput.IsEnabled = true;
PositionOfSmallViewsPolicy.Visibility = Visibility.Collapsed;
PositionOfSmallViewsPolicy.ToolTip = null;
}
else
{
PositionOfSmallViewsInput.IsEnabled = false;
PositionOfSmallViewsPolicy.Visibility = Visibility.Visible;
PositionOfSmallViewsPolicy.ToolTip = cMultiLanguageSupport.GetItem("Settings.Global.PolicyTooltip");
}
UpdatePolicyElements("SmallViewAlignment", PositionOfSmallViewsLabel, PositionOfSmallViewsInput, PositionOfSmallViewsPolicy);
OnPropertyChanged(nameof(PositionOfSmallViews));
// hide or deactivate FavouriteBarAlignment options due to the policies
_policy = cFasdCockpitConfig.Instance.Global.GetPropertyPolicy("FavouriteBarAlignment");
if (_policy == enumConfigPolicy.Hidden)
{
PositionOfFavouriteBarLabel.Visibility = Visibility.Collapsed;
PositionOfFavouriteBarInput.Visibility = Visibility.Collapsed;
}
else
{
PositionOfFavouriteBarLabel.Visibility = Visibility.Visible;
PositionOfFavouriteBarInput.Visibility = Visibility.Visible;
}
if (_policy == enumConfigPolicy.Default)
{
PositionOfFavouriteBarInput.IsEnabled = true;
PositionOfFavouriteBarPolicy.Visibility = Visibility.Collapsed;
PositionOfFavouriteBarPolicy.ToolTip = null;
}
else
{
PositionOfFavouriteBarInput.IsEnabled = false;
PositionOfFavouriteBarPolicy.Visibility = Visibility.Visible;
PositionOfFavouriteBarPolicy.ToolTip = cMultiLanguageSupport.GetItem("Settings.Global.PolicyTooltip");
}
UpdatePolicyElements("FavouriteBarAlignment", PositionOfFavouriteBarLabel, PositionOfFavouriteBarInput, PositionOfFavouriteBarPolicy);
OnPropertyChanged(nameof(PositionOfFavouriteBar));
UpdatePolicyElements(nameof(cFasdCockpitConfig.Instance.Global.UseGamification), UseGamificationLabel, UseGamificationCheckBox, UseGamifictationPolicy);
OnPropertyChanged(nameof(cFasdCockpitConfig.Instance.Global.UseGamification));
void UpdatePolicyElements(string policyName, FrameworkElement label, FrameworkElement control, FrameworkElement policyElement)
{
enumConfigPolicy policy = cFasdCockpitConfig.Instance.Global.GetPropertyPolicy(policyName);
label.Visibility = policy == enumConfigPolicy.Hidden ? Visibility.Collapsed : Visibility.Visible;
control.Visibility = policy == enumConfigPolicy.Hidden ? Visibility.Collapsed : Visibility.Visible;
control.IsEnabled = policy == enumConfigPolicy.Default;
policyElement.Visibility = policy == enumConfigPolicy.Default ? Visibility.Collapsed : Visibility.Visible;
policyElement.ToolTip = policy == enumConfigPolicy.Default ? null : cMultiLanguageSupport.GetItem("Settings.Global.PolicyTooltip");
}
}
public void SetUpSettingsControls()
@@ -872,7 +813,7 @@ namespace FasdDesktopUi.Pages.SettingsPage
{
try
{
_Instance = null;
_instance = null;
if (cSupportCaseDataProvider.detailsPage?.Visibility == Visibility.Visible)
await cSupportCaseDataProvider.detailsPage.AdjustWindowSizeAsync();
}

View File

@@ -101,9 +101,9 @@
Padding="10">
<Grid>
<buc:MenuBar x:Name="MenuBarUc" x:FieldModifier="private" />
<buc:SearchBar x:Name="SearchBarUserControl" x:FieldModifier="private"
Visibility="Collapsed"
/>
<buc:InformationClassSearchBar x:Name="SearchBarUserControl"
x:FieldModifier="private"
Visibility="Collapsed" />
</Grid>
</Border>

View File

@@ -45,8 +45,8 @@ namespace FasdDesktopUi.Pages.SlimPage
{
switch (invoker)
{
case SearchBar searchBar:
if (!searchBar.IsVisible || searchBar.SearchStatus != SearchBar.eSearchStatus.message)
case InformationClassSearchBar searchBar:
if (!searchBar.IsVisible || searchBar.SearchStatus != InformationClassSearchBar.eSearchStatus.message)
return true;
break;
case QuickActionSelector _:
@@ -256,7 +256,7 @@ namespace FasdDesktopUi.Pages.SlimPage
tempSubMenuList.Add(new cMenuDataBase(copyTemplate.Value));
}
tempMoreQuickActionList.Insert(0, new cMenuDataContainer() { MenuText = cMultiLanguageSupport.GetItem("QuickAction.CopyContent"), MenuIcon = new F4SD_AdaptableIcon.IconData(enumInternIcons.menuBar_copy), UiAction = new cSubMenuAction(true) { Name = cMultiLanguageSupport.GetItem("QuickAction.CopyContent"), SubMenuData = tempSubMenuList }, SubMenuData = tempSubMenuList });
tempMoreQuickActionList.Insert(0, new cMenuDataContainer() { MenuText = cMultiLanguageSupport.GetItem("QuickAction.CopyContent"), MenuIcon = new cMenuDataBase.MenuIconInfo(new F4SD_AdaptableIcon.IconData(enumInternIcons.menuBar_copy)), UiAction = new cSubMenuAction(true) { Name = cMultiLanguageSupport.GetItem("QuickAction.CopyContent"), SubMenuData = tempSubMenuList }, SubMenuData = tempSubMenuList });
}
var quickActionSelector = new QuickActionSelector()
@@ -403,7 +403,7 @@ namespace FasdDesktopUi.Pages.SlimPage
if (!(DataContext is SlimPageViewModel viewModel))
return;
if (SearchBarUserControl.SearchStatus != SearchBar.eSearchStatus.message)
if (SearchBarUserControl.SearchStatus != InformationClassSearchBar.eSearchStatus.message)
{
SearchBarUserControl.Visibility = Visibility.Collapsed;
MenuBarUc.Visibility = Visibility.Visible;

View File

@@ -15,6 +15,20 @@
WindowStyle="None"
IsVisibleChanged="Window_IsVisibleChanged">
<Window.Resources>
<Style x:Key="IconHoverStyle"
TargetType="ico:AdaptableIcon">
<Setter Property="Opacity"
Value="1" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Opacity"
Value="0.6" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Border Padding="12.5 7.5"
Background="#234B92">
<Grid>
@@ -30,31 +44,26 @@
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ico:AdaptableIcon x:Name="MinimizeButton"
Grid.Row="0"
Grid.Column="2"
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" HorizontalAlignment="Right">
<ico:AdaptableIcon x:Name="MinimizeButton"
PrimaryIconColor="White"
HorizontalAlignment="Right"
Cursor="Hand"
Style="{StaticResource IconHoverStyle}"
MouseLeftButtonUp="MinimizeButton_MouseLeftButtonUp"
TouchDown="MinimizeButton_TouchDown">
<ico:AdaptableIcon.Resources>
<Style TargetType="ico:AdaptableIcon">
<Setter Property="Opacity"
Value="1" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Opacity"
Value="0.6" />
</Trigger>
</Style.Triggers>
</Style>
</ico:AdaptableIcon.Resources>
<ico:AdaptableIcon.SelectedInternIcon>
window_minimize
</ico:AdaptableIcon.SelectedInternIcon>
</ico:AdaptableIcon>
TouchDown="MinimizeButton_TouchDown"
SelectedInternIcon="window_minimize"
>
</ico:AdaptableIcon>
<ico:AdaptableIcon x:Name="MaximizeButton"
PrimaryIconColor="White"
HorizontalAlignment="Right"
Cursor="Hand"
Style="{StaticResource IconHoverStyle}"
SelectedInternIcon="window_fullscreen"
MouseLeftButtonUp="F4SDLogo_MouseLeftButtonDown" TouchDown="F4SDLogo_TouchDown"
/>
</StackPanel>
<ico:AdaptableIcon Grid.Row="0"
Grid.RowSpan="3"
@@ -66,7 +75,9 @@
IconHeight="220"
IconWidth="330"
SelectedInternIcon="f4sd_product_logo"
MouseLeftButtonDown="F4SDLogo_MouseLeftButtonDown"/>
MouseLeftButtonDown="F4SDLogo_MouseLeftButtonDown"
TouchDown="F4SDLogo_TouchDown"
/>
<Image Source="pack://application:,,,/Resources/Consulting4ITWhite.png"
Width="90"

View File

@@ -108,7 +108,8 @@ namespace FasdDesktopUi.Pages.SplashScreenView
#endregion
private void F4SDLogo_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
private void StartIntro()
{
try
{
@@ -137,5 +138,16 @@ namespace FasdDesktopUi.Pages.SplashScreenView
LogException(ex);
}
}
private void F4SDLogo_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
StartIntro();
}
private void F4SDLogo_TouchDown(object sender, System.Windows.Input.TouchEventArgs e)
{
StartIntro();
}
}
}

View File

@@ -3,16 +3,17 @@ using FasdDesktopUi.Basics;
using FasdDesktopUi.Basics.Models;
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using WinForms = System.Windows.Forms;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using WinForms = System.Windows.Forms;
using static C4IT.Logging.cLogManager;
using F4SD.Gamification.Services;
namespace FasdDesktopUi.Pages.TicketCompletion
{
@@ -304,15 +305,16 @@ namespace FasdDesktopUi.Pages.TicketCompletion
bool closedSuccessfull = await CloseCaseDialogUc.CloseCaseAsync(_dataProvider.Identities.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.User).Id);
if (closedSuccessfull)
{
SuccessPage.SuccessPage successPage = new SuccessPage.SuccessPage();
successPage.Show();
await _dataProvider?.CloseCaseAsync();
TrySetDialogResult(true);
Close();
}
}
if (closedSuccessfull)
{
SuccessPage.SuccessPage successPage = new SuccessPage.SuccessPage();
successPage.Show();
GamificationService.TrackAction(F4SD.Gamification.CockpitAction.CaseClosed);
await _dataProvider?.CloseCaseAsync();
TrySetDialogResult(true);
Close();
}
}
catch (Exception E)
{
LogException(E);

View File

@@ -74,13 +74,13 @@
<SolidColorBrush x:Key="HorizontalLineColor">#414141</SolidColorBrush>
<!--ScrollBar Colors-->
<Color x:Key="ControlLightColor">#303030</Color>
<Color x:Key="ControlMediumColor">#303030</Color>
<Color x:Key="ControlDarkColor">#303030</Color>
<Color x:Key="ControlLightColor">#5A5A5A</Color>
<Color x:Key="ControlMediumColor">#5A5A5A</Color>
<Color x:Key="ControlDarkColor">#5A5A5A</Color>
<SolidColorBrush x:Key="Scrollbar.Track.Color">#404040</SolidColorBrush>
<SolidColorBrush x:Key="TestColor"
Color="MediumVioletRed"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ResourceDictionary>

View File

@@ -1,5 +1,10 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:C4IT.FASD.Base;assembly=F4SD-Cockpit-Client-Base"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter">
<vc:LanguageCultureConverter x:Key="LanguageBindingConverter" />
<Style x:Key="Customizable.Editable.TextBox"
TargetType="TextBox">
<Setter Property="Padding"
@@ -30,48 +35,58 @@
Value="{DynamicResource BackgroundColor.DetailsPage.Widget.Title}" />
</Style>
<Style x:Key="Customizable.Editable.TextBox.EditOnly"
TargetType="TextBox"
<Style x:Key="Customizable.Editable.TextBox.EditOnly"
TargetType="TextBox"
BasedOn="{StaticResource Customizable.Editable.TextBox.Background}">
<Setter Property="BorderBrush"
<Setter Property="BorderBrush"
Value="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}" />
<Setter Property="BorderThickness"
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Padding"
<Setter Property="Padding"
Value="10" />
<Setter Property="IsReadOnly"
<Setter Property="IsReadOnly"
Value="False" />
<Setter Property="AcceptsTab"
<Setter Property="AcceptsReturn"
Value="True" />
<Setter Property="AcceptsReturn"
<Setter Property="SpellCheck.IsEnabled"
Value="True" />
<Setter Property="Language"
Value="{Binding Source={x:Static base:cF4SDCockpitXmlConfig.Instance}, Path=HealthCardConfig.ProtocollLanguage, Converter={StaticResource ResourceKey=LanguageBindingConverter}, ConverterCulture=en-US}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Source={x:Static base:cF4SDCockpitXmlConfig.Instance}, Path=HealthCardConfig.ProtocollLanguage}"
Value="{x:Null}">
<Setter Property="SpellCheck.IsEnabled"
Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="MandatoryFieldBorderStyle"
<Style x:Key="MandatoryFieldBorderStyle"
TargetType="Border">
<Setter Property="Margin"
<Setter Property="Margin"
Value="0 5 0 0" />
<Setter Property="BorderThickness"
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Padding"
<Setter Property="Padding"
Value="0" />
<Setter Property="CornerRadius"
<Setter Property="CornerRadius"
Value="7.5" />
<Setter Property="Background"
<Setter Property="Background"
Value="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}" />
<Setter Property="BorderBrush"
<Setter Property="BorderBrush"
Value="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
<Setter Property="Background"
Value="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}" />
<Setter Property="BorderBrush"
<Setter Property="BorderBrush"
Value="{DynamicResource BackgroundColor.Menu.SubCategory}" />
</Trigger>
<Trigger Property="IsEnabled"
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Opacity"
<Setter Property="Opacity"
Value="0.5" />
</Trigger>
</Style.Triggers>

Some files were not shown because too many files have changed in this diff Show More