using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; 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; using C4IT.FASD.Base; using C4IT.FASD.Cockpit.Communication; using C4IT.Logging; using C4IT.MultiLanguage; using C4IT.XML; using F4SD_AdaptableIcon.Enums; using FasdDesktopUi.Basics.CustomEvents; using FasdDesktopUi.Basics.Enums; using FasdDesktopUi.Basics.Models; using FasdDesktopUi.Basics.UiActions; using FasdDesktopUi.Pages.DetailsPage.Models; using FasdDesktopUi.Pages.SlimPage.Models; using static C4IT.FASD.Base.cF4SDHealthCardRawData; using static C4IT.Logging.cLogManager; namespace FasdDesktopUi.Basics.Helper { public class cHealthCardDataHelper { #region Properties and fields private readonly IRawValueFormatter _rawValueFormatter = new RawValueFormatter(); private readonly cSupportCaseDataProvider dataProvider; private bool isInEditMode; public cHealthCard SelectedHealthCard { get; private set; } public cF4SDHealthCardRawData HealthCardRawData { get; private set; } = new cF4SDHealthCardRawData(); public Dictionary HeadingData { get; private set; } public DateTime? LastDataRequest { get; set; } = null; private readonly MenuItemDataProvider _menuDataProvider; public bool IsInEditMode { get => isInEditMode; set { isInEditMode = value; EditModeChanged?.Invoke(this, new BooleanEventArgs() { BooleanArg = value }); } } #endregion #region Events public event EventHandler DataChanged; public event EventHandler DataFullyLoaded; public event EventHandler DataRefreshed; public static event EventHandler EditModeChanged; #endregion public cHealthCardDataHelper(cSupportCaseDataProvider dataProvider) { this.dataProvider = dataProvider; _menuDataProvider = new MenuItemDataProvider(dataProvider); _rawValueFormatter.SetDefaultCulture(new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage)); } public void Reset() { try { HeadingData = null; if (HealthCardRawData?.Tables?.Count > 0) { var tablesToRemove = HealthCardRawData.Tables.Values.Select(value => value.InformationClass) .Distinct() .ToList(); RemoveTablesWithUpdatedIdentities(tablesToRemove); } } catch (Exception E) { LogException(E); } } public void RemoveTablesWithUpdatedIdentities(List updatedInformationClasses) { try { if (updatedInformationClasses.Count <= 0) return; //var dataProvider = cDataProviderBase.CurrentPorvider; if (dataProvider is null) return; var tablesToRemove = dataProvider.HealthCardDataHelper.HealthCardRawData?.Tables?.Where(table => updatedInformationClasses.Contains(table.Value.InformationClass)) .Select(table => table.Key) .ToArray(); foreach (var tableToRemove in tablesToRemove) { dataProvider.HealthCardDataHelper.HealthCardRawData?.Tables?.Remove(tableToRemove); } dataProvider.HealthCardDataHelper.HealthCardRawData?.Tables?.Remove("agnt-user"); dataProvider.HealthCardDataHelper.HealthCardRawData?.Tables?.Remove("agnt-computer"); } catch (Exception E) { LogException(E); } } #region GetHealthCardData public static bool HasAvailableHealthCard(List informationClasses) { try { if (informationClasses is null) return false; var _hc = cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.HealthCards?.Values; if (_hc != null) { foreach (var healthCard in _hc) { bool found = true; foreach (var informationClass in informationClasses) { found &= healthCard.InformationClasses.Any(healthCardInformationClass => healthCardInformationClass == informationClass); if (!found) break; } found &= HasCockpitUserRequiredRoles(healthCard.RequiredRoles); if (found) return true; } } } catch (Exception E) { LogException(E); } return false; } public bool TryGetHealthcard(List informationClasses) { try { if (informationClasses is null) return false; foreach (var healthCard in cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.HealthCards.Values) { bool found = true; foreach (var informationClass in informationClasses) { found &= healthCard.InformationClasses.Any(healthCardInformationClass => healthCardInformationClass == informationClass); if (!found) break; } found &= HasCockpitUserRequiredRoles(healthCard.RequiredRoles); if (found) { SelectedHealthCard = healthCard; return true; } } } catch (Exception E) { LogException(E); } finally { } return false; } private async Task ActualizeDataAsync() { var output = enumActualizeStatus.unknown; try { const int refreshDelayInMilliseconds = 500; const int maxPollCount = 20; if (dataProvider.Identities.Any(identity => identity.Class == enumFasdInformationClass.Computer) is false) { LogEntry("Coudldn't acutalize data. There was no information class of type computer found.", LogLevels.Error); return output; } if (dataProvider.NamedParameterEntries.TryGetValue("AgentDeviceId", out var agentDeviceIdParameter) is false || int.TryParse(agentDeviceIdParameter.GetValue(), out int agentDeviceId) is false) { LogEntry("Coudldn't acutalize data. There was no valid AgentDeviceId found.", LogLevels.Error); return output; } int? agentUserId = null; if (dataProvider.Identities.Any(identity => identity.Class == enumFasdInformationClass.User)) if (dataProvider.NamedParameterEntries.TryGetValue("AgentUserId", out var agentUserIdParameter)) if (int.TryParse(agentUserIdParameter.GetValue(), out int tempAgentUserId)) agentUserId = tempAgentUserId; var actualizeId = await cFasdCockpitCommunicationBase.Instance.ActualizeAgentData(agentDeviceId, agentUserId); if (actualizeId == Guid.Empty) return enumActualizeStatus.failed; enumFasdInformationClass informationClass = agentUserId != null ? enumFasdInformationClass.User : enumFasdInformationClass.Computer; int pollCount = 0; while (output == enumActualizeStatus.unknown) { output = await cFasdCockpitCommunicationBase.Instance.GetActualizeAgentDataStatus(actualizeId, informationClass); if (output == enumActualizeStatus.unknown) { pollCount++; if (pollCount >= maxPollCount) return output; await Task.Delay(refreshDelayInMilliseconds); } } } catch (Exception E) { LogException(E); } return output; } private void UpdateLatestValues(cF4SDHealthCardRawData newRawData) { try { if (newRawData is null) return; foreach (var tableName in newRawData.Tables.Keys) { try { if (HealthCardRawData.Tables.TryGetValue(tableName, out var oldTable) == false) continue; if (newRawData.Tables.TryGetValue(tableName, out var newTable) == false) continue; foreach (var oldColumn in oldTable.Columns) { try { if (newTable.Columns.TryGetValue(oldColumn.Key, out var newTableColumn) == false) continue; if (newTable.TableType != eDataHistoryTableType.HistoryEvents) { if (newTableColumn.Values is null || newTableColumn.Values?.Count <= 0) continue; if (oldColumn.Value?.Values is null || oldColumn.Value.Values.Count <= 0) continue; oldColumn.Value.Values[0] = newTableColumn.Values[0]; } else oldColumn.Value.Values = newTableColumn.Values; } catch (Exception E) { LogException(E); } } } catch (Exception E) { LogException(E); } } SelectedHealthCard.DoComputations(HealthCardRawData); LogEntry("DataChanged - Update Latest Values finished."); DataChanged?.Invoke(this, EventArgs.Empty); } catch (Exception E) { LogException(E); } } public async Task RefreshLatestDataAsync() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (dataProvider.DirectConnectionHelper.IsDirectConnectionActive) { var actualizeResult = await ActualizeDataAsync(); if (actualizeResult == enumActualizeStatus.failed) LogEntry("Failed to actualize data, due to server timeout.", LogLevels.Error); } var requiredTables = HealthCardRawData.Tables.Keys.Where(tableKey => tableKey.StartsWith("Computation_") is false).ToList(); if (requiredTables is null || requiredTables.Count <= 0) return; var request = new cF4sdHealthCardRawDataRequest() { Identities = dataProvider.Identities, Tables = requiredTables, MaxAge = cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.SearchResultAge ?? 14 }; //todo: reduce requested days to 1 await LoadingRawDataCriticalSection.EnterAsync(); try { var newRawData = await cFasdCockpitCommunicationBase.Instance.GetHealthCardData(request); UpdateLatestValues(newRawData); bool isRawDataIncomplete = false; do { isRawDataIncomplete = false; if (newRawData != null) { newRawData = await cFasdCockpitCommunicationBase.Instance.GetHealthCardData(newRawData.Id); UpdateLatestValues(newRawData); } if (newRawData?.Tables?.Count > 0) if (newRawData.Tables.Values.Any(table => table.IsIncomplete)) isRawDataIncomplete = true; } while (isRawDataIncomplete); LastDataRequest = DateTime.Now; DataRefreshed?.Invoke(this, EventArgs.Empty); DataFullyLoaded?.Invoke(this, EventArgs.Empty); } catch (Exception E) { LogException(E); } LoadingRawDataCriticalSection.Leave(); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } private bool CheckUpdatedTable(KeyValuePair table, cF4SDHealthCardRawData updatedHealthCardRawData) { if (!(updatedHealthCardRawData?.Tables?.ContainsKey(table.Key) is true)) return false; var _res = WasTableUpdated(table.Value, updatedHealthCardRawData.Tables[table.Key]); return _res; } private async Task ContinueHealthCardDataLoadingAsync() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { var IsDataIncomplete = true; do { try { var updatedHealthCardRawData = await cFasdCockpitCommunicationBase.Instance.GetHealthCardData(HealthCardRawData.Id); lock (HealthCardRawData) { var incompleteRawTables = HealthCardRawData.Tables.Where(table => table.Value.IsIncomplete && table.Key.StartsWith("Computation_") == false) .ToDictionary(table => table.Key, table => table.Value); if (updatedHealthCardRawData is null) { var _msg = new List { $"Couldn't recieve complete healthcard raw data with id {HealthCardRawData?.Id}.", " Incomplete health cards:" }; foreach (var incompleteTable in HealthCardRawData.Tables.Where(table => table.Value.IsIncomplete)) { _msg.Add($" {incompleteTable.Value.Name}"); foreach (var incompleteColumn in incompleteTable.Value.Columns.Values.Where(column => column.IsIncomplete)) { incompleteColumn.IsIncomplete = false; } incompleteTable.Value.IsIncomplete = false; } cLogManager.DefaultLogger.LogList(LogLevels.Error, _msg); SelectedHealthCard.DoComputations(HealthCardRawData); LogEntry("DataChanged - Couldn't complete healthcard raw data."); DataChanged?.Invoke(this, EventArgs.Empty); break; } var rawTablesToUpdate = incompleteRawTables.Where(table => CheckUpdatedTable(table, updatedHealthCardRawData)).ToDictionary(table => table.Key, table => table.Value); foreach (var oldTable in rawTablesToUpdate) { if (oldTable.Key.ToLowerInvariant() == "nxt-user") { } var newTable = updatedHealthCardRawData.Tables[oldTable.Key]; var oldTableValues = HealthCardRawData.Tables[oldTable.Key]; cF4SDHealthCardRawData.cHealthCardTable mergedTable = oldTableValues; foreach (var newTableColumnKeys in newTable.Columns.Keys) { if (mergedTable.Columns.ContainsKey(newTableColumnKeys) == false) mergedTable.Columns[newTableColumnKeys] = new cF4SDHealthCardRawData.cHealthCardTableColumn(); int mergedTableColumnValueCount = mergedTable.Columns[newTableColumnKeys].Values.Count; int mergedTableColumnLength = Math.Max(mergedTable.StartingIndex + mergedTableColumnValueCount, newTable.StartingIndex + newTable.Columns[newTableColumnKeys].Values.Count); //mergedTable.Columns[newTableColumnKeys].Values.Count + newTable.Columns.Count; object[] mergedTableColumnValues = new object[mergedTableColumnLength]; for (int i = mergedTable.StartingIndex; i < mergedTable.StartingIndex + mergedTableColumnValueCount; i++) { mergedTableColumnValues[i] = mergedTable.Columns[newTableColumnKeys].Values[i - mergedTable.StartingIndex]; } for (int i = newTable.StartingIndex; i < newTable.StartingIndex + newTable.Columns[newTableColumnKeys].Values.Count; i++) { mergedTableColumnValues[i] = newTable.Columns[newTableColumnKeys].Values[i - newTable.StartingIndex]; } int newStartingIndex = Math.Min(mergedTable.StartingIndex, newTable.StartingIndex); mergedTable.Columns[newTableColumnKeys].Values = mergedTableColumnValues.Skip(newStartingIndex).ToList(); mergedTable.Columns[newTableColumnKeys].IsIncomplete = newTable.Columns[newTableColumnKeys].IsIncomplete; mergedTable.StartingIndex = newStartingIndex; mergedTable.IsIncomplete = newTable.IsIncomplete; } HealthCardRawData.Tables[oldTable.Key] = mergedTable; } IsDataIncomplete = HealthCardRawData.Tables.Where(table => table.Key.StartsWith("Computation_") == false) .Any(table => table.Value.IsIncomplete); if (rawTablesToUpdate?.Count > 0) { SelectedHealthCard.DoComputations(HealthCardRawData); LogEntry($"DataChanged - {rawTablesToUpdate.Count} Tables where updated with last GetHealthcardData-Request."); DataChanged?.Invoke(this, EventArgs.Empty); } } } catch (Exception E) { LogException(E); } } while (IsDataIncomplete); DataFullyLoaded?.Invoke(this, new EventArgs()); } catch (Exception E) { LogException(E); } finally { LoadingRawDataCriticalSection.Leave(); LogMethodEnd(CM); } } public async Task GetHealthCardRawDataAsync(cF4sdHealthCardRawDataRequest requestData) { var CM = MethodBase.GetCurrentMethod(); var IsDataIncomplete = true; LogMethodBegin(CM); try { if (SelectedHealthCard == null) { LogEntry("No valid healthcard was found."); return false; } dataProvider.Identities = requestData.Identities; var requestedTables = requestData.Tables; HealthCardRawData.RemoveEmptyTables(); var requiredTables = requestedTables.Where(value => HealthCardRawData.Tables.ContainsKey(value) == false && value.StartsWith("Computation_") == false).ToList(); Mouse.OverrideCursor = Cursors.Wait; cF4SDHealthCardRawData newHealthCardRawData = null; await LoadingRawDataCriticalSection.EnterAsync(); IsDataIncomplete = false; if (requiredTables?.Count > 0) { requestData.Tables = requiredTables; newHealthCardRawData = await cFasdCockpitCommunicationBase.Instance.GetHealthCardData(requestData); if (newHealthCardRawData == null) return false; } if (newHealthCardRawData != null) HealthCardRawData = HealthCardRawData.Combine(newHealthCardRawData); UpdateNamedParameterEntries(); IsDataIncomplete = HealthCardRawData.Tables.Where(table => table.Key.StartsWith("Computation_") == false) .ToList() .Any(table => table.Value.IsIncomplete); if (IsDataIncomplete) { var _ = Task.Run(ContinueHealthCardDataLoadingAsync); } lock (HealthCardRawData) { SelectedHealthCard.DoComputations(HealthCardRawData); } LogEntry("DataChanged - Finished getting Healthcard rawdata."); DataChanged?.Invoke(this, new BooleanEventArgs() { BooleanArg = true }); UpdateNamedParameterEntries(); if (IsDataIncomplete is false) DataFullyLoaded?.Invoke(this, new EventArgs()); return true; } catch (Exception E) { LogException(E); } finally { if (IsDataIncomplete is false) LoadingRawDataCriticalSection.Leave(); Mouse.OverrideCursor = null; LogMethodEnd(CM); } return false; } #region Helper public static bool IsUiVisible(IUiVisibilityInformation visibilityInformation, cNamedParameterList NamedParameters = null) { if (visibilityInformation == null) return true; if (visibilityInformation.IsHidden) return false; if (!string.IsNullOrEmpty(visibilityInformation.IsVisibleByParameter)) if (!IsNamedParameterTrue(visibilityInformation.IsVisibleByParameter, NamedParameters)) return false; if (visibilityInformation.RequiredRoles != null && visibilityInformation.RequiredRoles.Count > 0) { if (!HasCockpitUserRequiredRoles(visibilityInformation.RequiredRoles)) return false; } return true; } private static bool HasCockpitUserRequiredRoles(List requiredRoles) { try { if (requiredRoles is null || requiredRoles.Count == 0) return true; List 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; } private List GetValuesOfHealthCardTableColumn(int startingIndex, cF4SDHealthCardRawData.cHealthCardTableColumn healthCardColumn) { List output = new List(); try { for (int i = 0; i < startingIndex; i++) { output.Add(null); } output.AddRange(healthCardColumn.Values); } catch (Exception E) { LogException(E); } return output; } private List GetStateValues(cValueAddress DatabaseInfo, bool isStatic) { List output = new List(); try { if (DatabaseInfo != null) { var healthCardTable = HealthCardRawData.GetTableByName(DatabaseInfo.ValueTable, isStatic); if (healthCardTable != null) if (healthCardTable.Columns.TryGetValue(DatabaseInfo.ValueColumn, out var healthCardColumn)) output = GetValuesOfHealthCardTableColumn(healthCardTable.StartingIndex, healthCardColumn); } } catch (Exception E) { LogException(E); } return output; } private bool IsValueIncomplete(cValueAddress databaseInfo, bool isStatic) { try { var healthCardTable = HealthCardRawData.GetTableByName(databaseInfo.ValueTable, isStatic); if (healthCardTable is null) return false; if (!healthCardTable.IsIncomplete) return false; if (!healthCardTable.Columns.TryGetValue(databaseInfo.ValueColumn, out var column)) return true; return column.IsIncomplete; } catch (Exception e) { LogException(e); } return false; } private object GetStateValueAt(cValueAddress DatabaseInfo, int index, bool isStatic) { var stateValues = GetStateValues(DatabaseInfo, isStatic); if (stateValues.Count <= index) return null; return stateValues[index]; } private enumHighlightColor GetHighlightColor(object value, cHealthCardStateBase stateDefinition, int referenceDays = 0) { return GetHighlightColor(new cStateThresholdValues() { Value = value, StateDefinition = stateDefinition, ReferenceDays = referenceDays }); } private enumHighlightColor GetHighlightColor(cStateThresholdValues thresholdValues) { enumHighlightColor output = enumHighlightColor.none; try { if (thresholdValues.Value == null) return output; if (thresholdValues.StateDefinition is cHealthCardStateLevel stateLevel) { var valueDouble = cF4SDHealthCardRawData.GetDouble(thresholdValues.Value); if (valueDouble != null) { if (stateLevel.IsDirectionUp) output = valueDouble >= stateLevel.Error ? enumHighlightColor.red : valueDouble >= stateLevel.Warning ? enumHighlightColor.orange : thresholdValues.StateDefinition.IsNotTransparent ? enumHighlightColor.green : enumHighlightColor.none; else output = valueDouble <= stateLevel.Error ? enumHighlightColor.red : valueDouble <= stateLevel.Warning ? enumHighlightColor.orange : thresholdValues.StateDefinition.IsNotTransparent ? enumHighlightColor.green : enumHighlightColor.none; } } else if (thresholdValues.StateDefinition is cHealthCardStateVersion stateVersion) { var valueVersion = cF4SDHealthCardRawData.GetVersion(thresholdValues.Value); if (valueVersion != null) { if (stateVersion.IsDirectionUp) output = valueVersion >= stateVersion.Error ? enumHighlightColor.red : valueVersion >= stateVersion.Warning ? enumHighlightColor.orange : thresholdValues.StateDefinition.IsNotTransparent ? enumHighlightColor.green : enumHighlightColor.none; else output = valueVersion <= stateVersion.Error ? enumHighlightColor.red : valueVersion <= stateVersion.Warning ? enumHighlightColor.orange : thresholdValues.StateDefinition.IsNotTransparent ? enumHighlightColor.green : enumHighlightColor.none; } } else if (thresholdValues.StateDefinition is cHealthCardStateDateTime stateDateTime) { var valueDateTime = cF4SDHealthCardRawData.GetDateTime(thresholdValues.Value); if (valueDateTime != null) { var tempDateTime = valueDateTime ?? DateTime.Now; var differenceHours = Math.Floor((DateTime.UtcNow.AddDays(-thresholdValues.ReferenceDays) - tempDateTime).TotalHours); if (stateDateTime.IsDirectionUp) output = differenceHours >= stateDateTime.ErrorHours ? enumHighlightColor.red : differenceHours >= stateDateTime.WarningHours ? enumHighlightColor.orange : thresholdValues.StateDefinition.IsNotTransparent ? enumHighlightColor.green : enumHighlightColor.none; else output = differenceHours <= stateDateTime.ErrorHours ? enumHighlightColor.red : differenceHours <= stateDateTime.WarningHours ? enumHighlightColor.orange : thresholdValues.StateDefinition.IsNotTransparent ? enumHighlightColor.green : enumHighlightColor.none; } } else if (thresholdValues.StateDefinition is cHealthCardStateInfo) { output = thresholdValues.StateDefinition.IsNotTransparent ? enumHighlightColor.blue : enumHighlightColor.none; } else if (thresholdValues.StateDefinition is cHealthCardStateTranslation stateTranslation) { var abstractTranslation = cF4SDHealthCardConfig.GetTranslationsWithName(stateTranslation, stateTranslation.Translation); if (abstractTranslation == null || !(abstractTranslation is cHealthCardTranslator translation)) return output; enumHealthCardStateLevel translationStateLevel = translation.DefaultTranslation?.StateLevel ?? enumHealthCardStateLevel.Info; foreach (var translationEntry in translation.Translations) { if (translationEntry.Values.Any(translationValue => thresholdValues.Value.ToString().Equals(translationValue, StringComparison.InvariantCultureIgnoreCase))) translationStateLevel = translationEntry.StateLevel; } switch (translationStateLevel) { case enumHealthCardStateLevel.None: output = enumHighlightColor.none; break; case enumHealthCardStateLevel.Ok: if (thresholdValues.StateDefinition.IsNotTransparent) output = enumHighlightColor.green; break; case enumHealthCardStateLevel.Warning: output = enumHighlightColor.orange; break; case enumHealthCardStateLevel.Error: output = enumHighlightColor.red; break; case enumHealthCardStateLevel.Info: if (thresholdValues.StateDefinition.IsNotTransparent) output = enumHighlightColor.blue; break; } } } catch (Exception E) { LogException(E); } return output; } private enumHighlightColor GetSummaryStatusColor(List stateDefinitions, bool isStatic, int dayIndex = 0) { enumHighlightColor output = enumHighlightColor.none; try { foreach (var stateDefinition in stateDefinitions) { if (!IsUiVisible(stateDefinition, dataProvider.NamedParameterEntries)) continue; var tempColor = enumHighlightColor.none; var stateValue = GetStateValueAt(stateDefinition.DatabaseInfo, dayIndex, isStatic); if (stateDefinition is cHealthCardStateAggregation aggregationState) tempColor = GetSummaryStatusColor(aggregationState.States, isStatic, dayIndex); else tempColor = GetHighlightColor(stateValue, stateDefinition, referenceDays: dayIndex); if (tempColor == enumHighlightColor.none && stateValue != null) tempColor = enumHighlightColor.green; output = (enumHighlightColor)Math.Max((int)tempColor, (int)output); } } catch (Exception E) { LogException(E); } return output; } private bool WasTableUpdated(cF4SDHealthCardRawData.cHealthCardTable oldTable, cF4SDHealthCardRawData.cHealthCardTable newTable) { try { if (oldTable.IsIncomplete && !newTable.IsIncomplete) return true; if (oldTable.StartingIndex != newTable.StartingIndex) return true; foreach (var oldTableColumn in oldTable.Columns.Values) { if (!newTable.Columns.TryGetValue(oldTableColumn.ColumnName, out var newTableColumn)) continue; if (oldTableColumn.Values.Count != newTableColumn.Values.Count) return true; } } catch (Exception E) { LogException(E); } return false; } #endregion #region Editable public List> GetEditInformationSelectionValues(cHealthCardStateBase stateDefinition) { List> output = null; try { if (!(stateDefinition.EditInfo is cStateEditableSelection editableSelectionInfo)) return output; List listValues = null; if (editableSelectionInfo.SelectionRawValueDatabaseInfo != null) listValues = GetStateValues(editableSelectionInfo.SelectionRawValueDatabaseInfo, false); List listDisplayValues = listValues.Select(value => value.ToString()).ToList(); if (editableSelectionInfo.SelectionDisplayValueDatabaseInfo != null) listDisplayValues = GetStateValues(editableSelectionInfo.SelectionDisplayValueDatabaseInfo, false) .Select(value => value.ToString()) .ToList(); if (editableSelectionInfo.Translation != null) { var translation = cF4SDHealthCardConfig.GetTranslationsWithName(stateDefinition, editableSelectionInfo.Translation); if (translation != null && translation is cHealthCardTranslator translator) { foreach (var displayValue in listDisplayValues.ToArray()) { var matchingTranslation = translator.Translations.FirstOrDefault(translatorTranslation => translatorTranslation.Values.Any(value => value.Equals(displayValue, StringComparison.InvariantCultureIgnoreCase))); if (matchingTranslation != null) listDisplayValues[listDisplayValues.IndexOf(displayValue)] = matchingTranslation.Translation.GetValue(); else listDisplayValues[listDisplayValues.IndexOf(displayValue)] = translator.DefaultTranslation?.Translation?.GetValue() ?? displayValue; } } } if (listValues.Count != listDisplayValues.Count) LogEntry($"The count of edit-values and edit-display-values doesn't match in the State '{stateDefinition.Name}'.", LogLevels.Warning); output = Enumerable .Zip(listValues, listDisplayValues, (value, displayValue) => new KeyValuePair(value, displayValue ?? value.ToString())) .ToList(); } catch (Exception E) { LogException(E); } return output; } public async Task UpdateHealthcardTableDataAsync(cValueAddress databaseInfo, object newValue) { bool output = false; try { var table = HealthCardRawData.GetTableByName(databaseInfo.ValueTable, false); if (table is null) return false; var identity = dataProvider.Identities.FirstOrDefault(identityEnty => identityEnty.Class == table.InformationClass); Guid id = identity?.Id ?? Guid.Empty; cF4SDWriteParameters updateParameter = new cF4SDWriteParameters() { id = id, TableName = databaseInfo.ValueTable, Values = new Dictionary() { [databaseInfo.ValueColumn] = newValue } }; await cFasdCockpitCommunicationBase.Instance.UpdateHealthcardTableData(updateParameter); } catch (Exception E) { LogException(E); } return output; } #endregion #region CustomizableSection public List GetContainerDataFromConfig(cHealthCardStateContainer containerConfig) { List output = new List(); try { if (containerConfig is null) return null; List containerHelpers = new List(); foreach (var stateContainerElementConfig in containerConfig.StateContainerElements) { var containerHelper = GetContainerHelperFromConfigElement(stateContainerElementConfig); containerHelpers.Add(containerHelper); } if (containerHelpers?.Count <= 0) return null; int maxValueCountOfContainerHelpers = containerHelpers.Max(helper => helper.MaxValueCount); for (int i = 0; i < maxValueCountOfContainerHelpers; i++) { var containerToAdd = new cContainerData() { IsMaximizable = containerConfig.IsMaximizable, IsAddable = containerConfig.IsAddable, IsDeletable = containerConfig.IsDeletable }; bool shouldSkipContainer = false; foreach (var containerHelper in containerHelpers) { var containerValue = GetContainerDataAtIndexFromHelper(containerHelper, i); containerToAdd.Add(containerValue); if (containerHelper.IsValueRequired && containerValue.HasValue is false) shouldSkipContainer = true; } if (shouldSkipContainer) continue; output.Add(containerToAdd); } } catch (Exception E) { LogException(E); } return output; } #endregion #region Page Common public List GetHeadingDataWithoutOnlineStatus() { Dictionary outputDictionary = new Dictionary(); var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (HeadingData != null) outputDictionary = HeadingData; var healthCardHeaderConfig = SelectedHealthCard.HeaderValues; bool isOnline = false; foreach (var headerValue in healthCardHeaderConfig) { string headingText = null; var selectedTable = HealthCardRawData.GetTableByName(headerValue.DatabaseInfo.ValueTable, true); if (selectedTable != null) if (selectedTable.Columns.TryGetValue(headerValue.DatabaseInfo.ValueColumn, out var selectedColumn)) headingText = cF4SDHealthCardRawData.GetString(selectedColumn.Values[0], null); cHeadingDataModel singleHeadingValue = null; if (outputDictionary != null && outputDictionary.TryGetValue(headerValue.InformationClass, out singleHeadingValue)) if (singleHeadingValue.IsOnline && singleHeadingValue.HeadingText.Equals(headingText)) continue; cF4sdIdentityList headingIdentities = dataProvider.Identities; singleHeadingValue = new cHeadingDataModel() { InformationClass = headerValue.InformationClass, HeadingText = headingText, IsOnline = isOnline, Identities = headingIdentities }; outputDictionary[headerValue.InformationClass] = singleHeadingValue; } foreach (enumFasdInformationClass informationClass in Enum.GetValues(typeof(enumFasdInformationClass))) { if (outputDictionary.ContainsKey(informationClass)) continue; string headingText = string.Empty; switch (informationClass) { case enumFasdInformationClass.Computer: headingText = cMultiLanguageSupport.GetItem("Header.Select.Computer"); break; case enumFasdInformationClass.Ticket: headingText = cMultiLanguageSupport.GetItem("Header.Select.Ticket"); break; case enumFasdInformationClass.VirtualSession: headingText = cMultiLanguageSupport.GetItem("Header.Select.VirtualSession"); break; case enumFasdInformationClass.MobileDevice: headingText = cMultiLanguageSupport.GetItem("Header.Select.MobileDevice"); break; } outputDictionary[informationClass] = new cHeadingDataModel() { InformationClass = informationClass, HeadingText = headingText }; } HeadingData = outputDictionary; } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return outputDictionary.Values.ToList(); } private async Task> GetHeadingDataAsync() { Dictionary outputDictionary = new Dictionary(); var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (HeadingData != null) outputDictionary = HeadingData; var healthCardHeaderConfig = SelectedHealthCard.HeaderValues; bool isOnline = false; foreach (var headerValue in healthCardHeaderConfig) { string headingText = null; var selectedTable = HealthCardRawData.GetTableByName(headerValue.DatabaseInfo.ValueTable, true); if (selectedTable != null) if (selectedTable.Columns.TryGetValue(headerValue.DatabaseInfo.ValueColumn, out var selectedColumn)) headingText = cF4SDHealthCardRawData.GetString(selectedColumn.Values[0], null); cHeadingDataModel singleHeadingValue = null; if (outputDictionary != null) outputDictionary.TryGetValue(headerValue.InformationClass, out singleHeadingValue); cF4sdIdentityList headingIdentities = dataProvider.Identities; switch (headerValue.InformationClass) { case enumFasdInformationClass.Computer: if (dataProvider.NamedParameterEntries.TryGetValue("AgentDeviceId", out var agentDeviceIdParameter)) if (int.TryParse(agentDeviceIdParameter.GetValue(), out int agentDeviceId)) isOnline = await cFasdCockpitCommunicationBase.Instance.GetAgentOnlineStatus(agentDeviceId); break; case enumFasdInformationClass.User: if (dataProvider.NamedParameterEntries.TryGetValue("AgentDeviceId", out var agentDeviceIdParameterUserContext)) if (int.TryParse(agentDeviceIdParameterUserContext.GetValue(), out int agentDeviceId)) if (dataProvider.NamedParameterEntries.TryGetValue("AgentUserId", out var agentUserIdParameter)) if (int.TryParse(agentUserIdParameter.GetValue(), out int agentUserId)) isOnline = await cFasdCockpitCommunicationBase.Instance.GetAgentOnlineStatus(agentDeviceId, agentUserId); break; case enumFasdInformationClass.Ticket: //todo: check ticket status not via stored relations! if (dataProvider.CaseRelations != null && dataProvider.CaseRelations.TryGetValue(enumFasdInformationClass.Ticket, out var ticketValues)) { var selectedTicket = ticketValues.FirstOrDefault(value => dataProvider.Identities.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.Ticket)?.Id == value.id); if (selectedTicket != null) { if (selectedTicket.Infos.TryGetValue("StatusId", out var statusIdString)) { Enum.TryParse(statusIdString, out enumTicketStatus statusId); isOnline = statusId != enumTicketStatus.Closed; } } } break; case enumFasdInformationClass.VirtualSession: if (dataProvider.CaseRelations != null && dataProvider.CaseRelations.TryGetValue(enumFasdInformationClass.VirtualSession, out var virtualSessionValues)) { var selectedVirtualSession = virtualSessionValues.FirstOrDefault(value => dataProvider.Identities.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.VirtualSession)?.Id == value.id); if (selectedVirtualSession != null) { if (selectedVirtualSession.Infos.TryGetValue("Status", out var statusIdString)) { Enum.TryParse(statusIdString, out enumCitrixSessionStatus statusId); isOnline = statusId == enumCitrixSessionStatus.Active; } } } break; case enumFasdInformationClass.MobileDevice: //todo: check ticket status not via stored relations! if (dataProvider.CaseRelations != null && dataProvider.CaseRelations.TryGetValue(enumFasdInformationClass.MobileDevice, out var mobileDeviceValues)) { var selectedMobileDevice = mobileDeviceValues.FirstOrDefault(value => dataProvider.Identities.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.MobileDevice)?.Id == value.id); } break; } singleHeadingValue = new cHeadingDataModel() { InformationClass = headerValue.InformationClass, HeadingText = headingText, IsOnline = isOnline, Identities = headingIdentities }; outputDictionary[headerValue.InformationClass] = singleHeadingValue; } foreach (enumFasdInformationClass informationClass in Enum.GetValues(typeof(enumFasdInformationClass))) { if (outputDictionary.ContainsKey(informationClass)) continue; string headingText = string.Empty; switch (informationClass) { case enumFasdInformationClass.Computer: headingText = cMultiLanguageSupport.GetItem("Header.Select.Computer"); break; case enumFasdInformationClass.Ticket: headingText = cMultiLanguageSupport.GetItem("Header.Select.Ticket"); break; } outputDictionary[informationClass] = new cHeadingDataModel() { InformationClass = informationClass, HeadingText = headingText }; } HeadingData = outputDictionary; } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return outputDictionary.Values.ToList(); } public async Task> UpdateOnlineStatusAsync() { try { if (HeadingData is null) return null; if (dataProvider.NamedParameterEntries.TryGetValue("AgentDeviceId", out var agentDeviceIdParameter)) if (int.TryParse(agentDeviceIdParameter.GetValue(), out int agentDeviceId)) HeadingData[enumFasdInformationClass.Computer].IsOnline = await cFasdCockpitCommunicationBase.Instance.GetAgentOnlineStatus(agentDeviceId); if (dataProvider.NamedParameterEntries.TryGetValue("AgentDeviceId", out var agentDeviceIdParameterUserContext)) if (int.TryParse(agentDeviceIdParameterUserContext.GetValue(), out int agentDeviceId)) if (dataProvider.NamedParameterEntries.TryGetValue("AgentUserId", out var agentUserIdParameter)) if (int.TryParse(agentUserIdParameter.GetValue(), out int agentUserId)) HeadingData[enumFasdInformationClass.User].IsOnline = await cFasdCockpitCommunicationBase.Instance.GetAgentOnlineStatus(agentDeviceId, agentUserId); } catch (Exception E) { LogException(E); } return HeadingData?.Values?.ToList(); } private List GetMenuBarData() => _menuDataProvider.GetMenuItemData() .Where(data => (data.MenuSections?.Count == 0 || data.IconPositionIndex > -1) && data.UiAction?.DisplayType != enumActionDisplayType.hidden) .ToList(); #endregion #region SlimPage private List> GetWidgetDataSlim() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); var output = new List>(); try { var healthCardWidgetConfig = SelectedHealthCard.CategoriesStaticSlim; foreach (var categoryDefinition in healthCardWidgetConfig.StateCategories) { if (!IsUiVisible(categoryDefinition, dataProvider.NamedParameterEntries)) continue; var widgetValues = new List(); foreach (var stateDefinition in categoryDefinition.States) { if (!IsUiVisible(stateDefinition, dataProvider.NamedParameterEntries)) continue; if (HealthCardRawData.Tables.ContainsKey(stateDefinition.DatabaseInfo?.ValueTable) == false) continue; var stateModel = stateDefinition; var widgetValueToAdd = new cWidgetValueModel { TechnicalName = stateDefinition.ParameterName }; if (!stateDefinition.IsTitleOptional && stateDefinition.Names.Count > 0) widgetValueToAdd.Title = stateDefinition.Names.GetValue(); if (stateDefinition.DatabaseInfo != null) { object widgetValue = GetStateValueAt(stateDefinition.DatabaseInfo, 0, true); widgetValueToAdd.Value = _rawValueFormatter.GetDisplayValue(widgetValue, cUtility.GetRawValueType(stateDefinition.DisplayType)); if (stateDefinition is cHealthCardStateRefLink refLinkState) { stateModel = cF4SDHealthCardConfig.GetReferencableStateWithName(stateDefinition.ParentNode, refLinkState.Reference); widgetValue = GetStateValueAt(stateModel.DatabaseInfo, 0, true); } var widgetHighlightColor = GetHighlightColor(widgetValue, stateModel); widgetValueToAdd.HighlightIn = widgetHighlightColor; widgetValues.Add(widgetValueToAdd); } } if (widgetValues?.Count <= 0) continue; output.Add(widgetValues); } } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return output; } private List GetSlimPageHistoryData() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); List output = new List(); try { var healthCardHistoryConfig = SelectedHealthCard.CategoriesHistory; if (healthCardHistoryConfig is null) return output; foreach (var categoryDefinition in healthCardHistoryConfig.StateCategories) { if (!IsUiVisible(categoryDefinition, dataProvider.NamedParameterEntries)) continue; var slimPageData = new cSlimPageDataHistoryModel() { Content = categoryDefinition.Names.GetValue(), ContentDescription = categoryDefinition.Descriptions.GetValue(), ValueColumns = new List() }; for (int i = 0; i < 6; i++) { bool isLoading = false; foreach (var stateDefinition in categoryDefinition?.States) { if (!IsUiVisible(stateDefinition, dataProvider.NamedParameterEntries)) continue; if (stateDefinition.DatabaseInfo != null) { var stateTable = HealthCardRawData.GetTableByName(stateDefinition.DatabaseInfo.ValueTable, false); if (stateTable != null) { int tableColumnCount = 0; try { if (stateTable?.Columns?.Count > 0) tableColumnCount = stateTable.Columns.Max(column => column.Value?.Values?.Count ?? 1); //todo: check for better implementation } catch { } if (i < stateTable.StartingIndex || i >= stateTable.StartingIndex + tableColumnCount) isLoading = stateTable.IsIncomplete; } } } var tempContent = i != 0 ? DateTime.Today.AddDays(-i).ToString("dd.MM") : cMultiLanguageSupport.GetItem("Global.Date.Today"); var tempHighlightColor = GetSummaryStatusColor(categoryDefinition.States, false, i); slimPageData.ValueColumns.Add(new cDataHistoryValueModel() { Content = tempContent, HighlightColor = tempHighlightColor, IsLoading = isLoading }); } //SummaryValueColumn var summaryValueColumnContent = $"{DateTime.Today.AddDays(-7):dd.MM} - {DateTime.Today.AddDays(-14):dd.MM}"; enumHighlightColor summaryValueColumnColor = enumHighlightColor.none; bool isSummaryLoading = false; for (int i = 7; i < 14; i++) { foreach (var stateDefinition in categoryDefinition?.States) { if (!IsUiVisible(stateDefinition, dataProvider.NamedParameterEntries)) continue; if (stateDefinition.DatabaseInfo != null) { var stateTable = HealthCardRawData.GetTableByName(stateDefinition.DatabaseInfo.ValueTable, false); if (stateTable != null) { int tableColumnCount = 0; try { if (stateTable?.Columns?.Count > 0) tableColumnCount = stateTable.Columns.Max(column => column.Value?.Values?.Count ?? 1); } catch { } if (i < stateTable.StartingIndex || i >= stateTable.StartingIndex + tableColumnCount) { isSummaryLoading = stateTable.IsIncomplete; break; } } } } summaryValueColumnColor = (enumHighlightColor)Math.Max((int)summaryValueColumnColor, (int)GetSummaryStatusColor(categoryDefinition.States, false, i)); } var summaryValueColumn = new cDataHistoryValueModel() { Content = summaryValueColumnContent, HighlightColor = summaryValueColumnColor, IsLoading = isSummaryLoading }; slimPageData.ValueColumns.Add(summaryValueColumn); output.Add(slimPageData); } } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return output; } public async Task GetSlimPageDataAsync() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); cSlimPageData output = new cSlimPageData(); try { if (SelectedHealthCard == null) return output; output.DataProvider = dataProvider; output.HeadingData = await GetHeadingDataAsync(); output.WidgetData = GetWidgetDataSlim(); output.DataHistoryList = GetSlimPageHistoryData(); output.MenuBarData = GetMenuBarData(); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return output; } #endregion #region DetailsPage private cHealthCardDetailsTable GetDetailTableValued(object _value, cHealthCardDetailsValued StateDetailsValued) { MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); } try { if (_value == null) return null; var _strData = _rawValueFormatter.GetDisplayValue(_value, RawValueType.STRING); if (_strData == null) return null; var _cols = new List(); foreach (var _colConfig in StateDetailsValued) _cols.Add(_colConfig.Names.GetValue()); var _arrRow = _strData.Split(StateDetailsValued.RowSeparator); var _values = new List(); foreach (var _row in _arrRow) { if (string.IsNullOrEmpty(_row)) continue; var _entry = new List(); if (StateDetailsValued.ColSeparator == null) _entry.Add(_row.Trim()); else { var _arrCol = _strData.Split((char)StateDetailsValued.ColSeparator); foreach (var _col in _arrCol) _entry.Add(_col.Trim()); } while (_entry.Count < _cols.Count) _entry.Add(null); _values.Add(_entry.ToArray()); } var Result = new cHealthCardDetailsTable() { Name = "Details-" + StateDetailsValued.ParentState.Name, Columns = _cols, Values = new Dictionary>() { { 0, _values } } }; return Result; } catch (Exception E) { LogException(E); } finally { if (CM != null) LogMethodEnd(CM); } return null; } private cWidgetValueModel GetWidgetRowData(cHealthCardStateBase stateDefinition) { try { if (!IsUiVisible(stateDefinition, dataProvider.NamedParameterEntries)) return null; var widgetRowData = new cWidgetValueModel { Title = stateDefinition.Names?.GetValue(), TechnicalName = stateDefinition.ParameterName, IsLoading = IsValueIncomplete(stateDefinition.DatabaseInfo, true), Value = "N/A", UiActionTitle = GetUiActionByQuickActionNames(stateDefinition.QuickActions, stateDefinition.Names.GetValue(), stateDefinition.Descriptions.GetValue()) }; if (stateDefinition.DatabaseInfo is null) return widgetRowData; object rawValueDisplay = GetStateValueAt(stateDefinition.DatabaseInfo, 0, true); object rawValueLeveling = rawValueDisplay; cHealthCardStateBase stateDefinitionForLeveling = stateDefinition; if (stateDefinition is cHealthCardStateRefLink refLinkState) rawValueLeveling = GetRawValueOf(refLinkState, out stateDefinitionForLeveling); widgetRowData.EditValueInformation = GetEditInfo(rawValueDisplay); widgetRowData.HighlightIn = stateDefinitionForLeveling is cHealthCardStateAggregation aggregation ? GetSummaryStatusColor(aggregation.States, true) : GetHighlightColor(rawValueLeveling, stateDefinitionForLeveling); bool shouldShowValueDetails = (TryGetValuedDetails(rawValueDisplay, out var valuedDetails) && valuedDetails?.Values?.Values?.FirstOrDefault()?.Count > 1) || (stateDefinition.Details is cHealthCardDetails && rawValueDisplay != null && rawValueDisplay.ToString() != "0"); if (shouldShowValueDetails) { widgetRowData.ValuedDetails = valuedDetails; widgetRowData.UiActionValue = new cShowDetailedDataAction(stateDefinition, ValuedDetailsData: valuedDetails) { DisplayType = enumActionDisplayType.enabled }; } widgetRowData.Value = GetDisplayValue(rawValueDisplay, valuedDetails); return widgetRowData; } catch (Exception ex) { LogException(ex); } return null; object GetRawValueOf(cHealthCardStateRefLink refLinkState, out cHealthCardStateBase referencedStateDefinition) { referencedStateDefinition = cF4SDHealthCardConfig.GetReferencableStateWithName(refLinkState.ParentNode, refLinkState.Reference); if (referencedStateDefinition?.DatabaseInfo is null) return null; return GetStateValueAt(referencedStateDefinition.DatabaseInfo, 0, true); } cEditableValueInformationBase GetEditInfo(object rawValue) { if (stateDefinition?.EditInfo is null) return null; switch (stateDefinition.EditInfo) { //todo: add Ids to editableInformation case cStateEditableSelection editableSelectionInfo: var editSelectionValues = GetEditInformationSelectionValues(stateDefinition); return new cEditValueInformationSelection() { CurrentValue = rawValue, Description = stateDefinition.Names.GetValue(), DatabaseInfo = stateDefinition.DatabaseInfo, SelectionValues = editSelectionValues }; case cStateEditableText edtiableTextInfo: var editValue = new List(1) { rawValue }; return new cEditValueInformationText() { CurrentValue = rawValue, Description = stateDefinition.Names.GetValue(), DatabaseInfo = stateDefinition.DatabaseInfo }; default: return null; } } string GetDisplayValue(object rawValue, cHealthCardDetailsTable detailTable) { string displayValue = null; if (stateDefinition is cHealthCardStateTranslation translationDefinition) displayValue = GetTranslationValue(translationDefinition, rawValue); if (detailTable != null) displayValue = GetDetailStringValue(rawValue, detailTable); return displayValue ?? _rawValueFormatter.GetDisplayValue(rawValue, cUtility.GetRawValueType(stateDefinition.DisplayType)); } string GetTranslationValue(cHealthCardStateTranslation translationDefinition, object rawValue) { ITranslatorObject abstractTranslation = cF4SDHealthCardConfig.GetTranslationsWithName(translationDefinition, translationDefinition.Translation); if (abstractTranslation is null || !(abstractTranslation is cHealthCardTranslator translation)) return null; if (rawValue is null) return translation.DefaultTranslation?.Translation?.GetValue(); var translationValue = translation.DefaultTranslation?.Translation?.GetValue() ?? rawValue.ToString(); foreach (var translationEntry in translation.Translations) { if (translationEntry.Values.Any(value => rawValue.ToString().Equals(value, StringComparison.InvariantCultureIgnoreCase))) return translationEntry.Translation.GetValue(); } return translationValue; } string GetDetailStringValue(object rawValue, 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 _rawValueFormatter.GetDisplayValue(detailTableValueTable.Values.First().Value.First()?.First(), cUtility.GetRawValueType(stateDefinition.Details.First().DisplayType)); else return _rawValueFormatter.GetDisplayValue(detailTableValueTable.Values.First().Value.Count, RawValueType.STRING); } bool TryGetValuedDetails(object rawValue, out cHealthCardDetailsTable valuedDetails) { valuedDetails = null; if (!(stateDefinition.Details is cHealthCardDetailsValued detailsValued)) return false; valuedDetails = GetDetailTableValued(rawValue, detailsValued); return true; } } private List> GetWidgetsData() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { return SelectedHealthCard.CategoriesStatic.StateCategories .Where(widgetDefinition => IsUiVisible(widgetDefinition, dataProvider.NamedParameterEntries)) .Select(widgetDefinition => GetWidgetData(widgetDefinition)) .ToList(); } catch (Exception ex) { LogException(ex); } finally { LogMethodEnd(CM); } return new List>(); List GetWidgetData(cHealthCardStateCategory widgetDefinition) { try { return widgetDefinition.States.Select(GetWidgetRowData) .Where(value => value != null) .ToList(); } catch (Exception ex) { LogException(ex); } return new List(); } } private cUiActionBase GetUiActionByQuickActionNames(List names, string uiActionName, string uiActionDescription) { try { if (names?.Count is null || names.Count == 0) return null; if (names.Count > 1) { List uiActions = _menuDataProvider.GetMenuItemData() .Where(data => names.Contains(data.UiAction.Name) && data.UiAction.DisplayType != enumActionDisplayType.hidden) .OrderBy(action => names.IndexOf(action.UiAction.Name)) .Select(action => SelectWithRecommendation(action, uiActionName, uiActionDescription)) .ToList(); if (uiActions?.Count == 0) return null; if (uiActions?.Count == 1) return uiActions[0].UiAction; return new cSubMenuAction(false) { SubMenuData = uiActions, Name = uiActionName, Description = uiActionDescription, DisplayType = enumActionDisplayType.enabled }; } else { string quickActionName = names[0]; if (string.IsNullOrWhiteSpace(quickActionName)) return null; cUiActionBase uiAction = _menuDataProvider.GetMenuItemData() // .Where(data => data is cUiQuickAction) .FirstOrDefault(data => data.UiAction.Name == quickActionName && data.UiAction.DisplayType == enumActionDisplayType.enabled)?.UiAction; if (uiAction is cUiQuickAction uiQuickAction) uiQuickAction.QuickActionRecommendation = new cRecommendationDataModel() { Category = uiActionName, Recommendation = uiActionDescription }; return uiAction; } } catch (Exception E) { LogException(E); } return null; cMenuDataBase SelectWithRecommendation(cMenuDataBase menuData, string category, string recommendation) { if (!(menuData.UiAction is cUiQuickAction uiQuickAction)) return menuData; uiQuickAction.QuickActionRecommendation = new cRecommendationDataModel() { Category = category, Recommendation = recommendation }; return menuData; } } private DetailsPageDataHistoryValueModel GetTitleColumnOfHealthCardState(cHealthCardStateBase stateDefinition) { DetailsPageDataHistoryValueModel output = null; try { var titleRowContent = stateDefinition.Names.GetValue(); var titleRowDescription = stateDefinition.Descriptions.GetValue(Default: titleRowContent); var titleRowPresentationStyle = stateDefinition is cHealthCardStateAggregation ? enumHistoryTitleType.aggregate : enumHistoryTitleType.header; cUiActionBase titleRowQuickAction = GetUiActionByQuickActionNames(stateDefinition.QuickActions, stateDefinition.Names.GetValue(), stateDefinition.Descriptions.GetValue(Default: null)); output = new DetailsPageDataHistoryValueModel() { Content = titleRowContent, ContentDescription = titleRowDescription, PresentationStyle = titleRowPresentationStyle, UiAction = titleRowQuickAction }; } catch (Exception E) { LogException(E); } return output; } private void ProcessHealthCardState(cHealthCardStateBase stateDefinition, int valueColumnCount, bool isStatic, ref List historySectionValueColumns) { var stateValues = GetStateValues(stateDefinition.DatabaseInfo, isStatic); //in case state is translationstate, get translation to avoid calling GetTranslationWithName method for every column cHealthCardStateTranslation stateTranslation = null; cHealthCardTranslator translation = null; if (stateDefinition is cHealthCardStateTranslation tempStateTranslation) { stateTranslation = tempStateTranslation; var abstractTranslation = cF4SDHealthCardConfig.GetTranslationsWithName(tempStateTranslation, stateTranslation.Translation); if (abstractTranslation is cHealthCardTranslator castedTranslation) translation = castedTranslation; } for (int i = 0; i < valueColumnCount; i++) { string cellContentString = stateDefinition is cHealthCardStateAggregation ? "Ø" : "-"; enumHighlightColor cellContentColor = enumHighlightColor.none; cStateThresholdValues thresholdValues = null; if (stateValues.Count > i) { FormattingOptions options = new FormattingOptions() { ReferenceDate = DateTime.UtcNow.Date.AddDays(i) }; thresholdValues = new cStateThresholdValues() { Value = stateValues[i], StateDefinition = stateDefinition, ReferenceDays = i }; cellContentString = _rawValueFormatter.GetDisplayValue(stateValues[i], cUtility.GetRawValueType(stateDefinition.DisplayType), options); if (string.IsNullOrWhiteSpace(cellContentString)) cellContentString = "-"; cellContentColor = GetHighlightColor(thresholdValues); } if (stateDefinition is cHealthCardStateAggregation stateAggregation) { cellContentColor = GetSummaryStatusColor(stateAggregation.States, isStatic, i); } if (stateTranslation != null) { if (translation != null && cellContentString != "-") { var translationValue = translation.DefaultTranslation?.Translation.GetValue() ?? cellContentString; foreach (var translationEntry in translation.Translations) { if (cellContentString != null) if (translationEntry.Values.Any(value => cellContentString.Equals(value, StringComparison.CurrentCultureIgnoreCase))) translationValue = translationEntry.Translation.GetValue(); } cellContentString = translationValue; } } bool isStateRowLoading = false; if (stateDefinition.DatabaseInfo != null) { var stateTable = HealthCardRawData.GetTableByName(stateDefinition.DatabaseInfo.ValueTable, isStatic); if (stateTable != null) { int maxColumnCount = 0; if (stateTable?.Columns?.Count > 0) maxColumnCount = stateTable.Columns.Max(column => column.Value?.Values?.Count ?? 1); if (i < stateTable.StartingIndex || i >= stateTable.StartingIndex + maxColumnCount) isStateRowLoading = stateTable.IsIncomplete; } } if (stateDefinition.DatabaseInfo != null) { var stateTable = HealthCardRawData.GetTableByName(stateDefinition.DatabaseInfo.ValueTable, isStatic); if (stateTable != null) if (stateTable.Columns.TryGetValue(stateDefinition.DatabaseInfo.ValueColumn, out var stateColumn)) isStateRowLoading = stateColumn.IsIncomplete; } var cellContent = new DetailsPageDataHistoryValueModel() { Content = cellContentString, HighlightColor = cellContentColor, IsLoading = isStateRowLoading, ThresholdValues = thresholdValues }; if (stateDefinition.Details != null && stateValues?.Count > i && stateValues[i] != null) cellContent.UiAction = new cShowDetailedDataAction(stateDefinition, i); historySectionValueColumns[i].ColumnValues.Add(cellContent); } } private List GetDetailsPageHistoryData() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); List output = new List(); try { var healthCardHistoryConfig = SelectedHealthCard.CategoriesHistory; if (healthCardHistoryConfig is null) return output; foreach (var stateCategoryDefinition in healthCardHistoryConfig.StateCategories) { if (!IsUiVisible(stateCategoryDefinition, dataProvider.NamedParameterEntries)) continue; var categoryContent = stateCategoryDefinition.Names.GetValue(); var categoryContentDescription = stateCategoryDefinition.Descriptions.GetValue(Default: categoryContent); cUiActionBase categoryQuickAction = GetUiActionByQuickActionNames(stateCategoryDefinition.QuickActions, stateCategoryDefinition.Names.GetValue(), stateCategoryDefinition.Descriptions.GetValue(Default: null)); var titleColumn = new DetailsPageDataHistoryColumnModel() //todo: refactor, see same code in titleRow { Content = categoryContent, ContentDescription = categoryContentDescription, UiAction = categoryQuickAction, ColumnValues = new List() }; // Adding columns to history section int valueColumnCount = SelectedHealthCard.MaxAgeInDays; var historySectionValueColumns = new List(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"); var summaryStatusColor = GetSummaryStatusColor(stateCategoryDefinition.States, false, i); var valueColumn = new DetailsPageDataHistoryColumnModel() { ColumnValues = new List(), Content = valueColumnHeader, HighlightColor = summaryStatusColor }; historySectionValueColumns.Add(valueColumn); } foreach (var stateDefinition in stateCategoryDefinition.States) { if (!IsUiVisible(stateDefinition, dataProvider.NamedParameterEntries)) continue; if (stateDefinition.DatabaseInfo != null && HealthCardRawData.Tables.ContainsKey(stateDefinition.DatabaseInfo.ValueTable) == false) continue; var titleRowData = GetTitleColumnOfHealthCardState(stateDefinition); if (titleRowData != null) titleColumn.ColumnValues.Add(titleRowData); ProcessHealthCardState(stateDefinition, valueColumnCount, false, ref historySectionValueColumns); //StateAggregation if (stateDefinition is cHealthCardStateAggregation stateAggregationDefinition) { foreach (var aggregatedStateDefinition in stateAggregationDefinition.States) { if (!IsUiVisible(aggregatedStateDefinition, dataProvider.NamedParameterEntries)) continue; var aggregatedTitleRowData = GetTitleColumnOfHealthCardState(aggregatedStateDefinition); if (aggregatedStateDefinition != null) { aggregatedTitleRowData.PresentationStyle = enumHistoryTitleType.subValue; titleColumn.ColumnValues.Add(aggregatedTitleRowData); } ProcessHealthCardState(aggregatedStateDefinition, valueColumnCount, false, ref historySectionValueColumns); } } } output.Add(new cDetailsPageDataHistoryDataModel() { TitleColumn = titleColumn, ValueColumns = historySectionValueColumns }); } } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return output; } private static bool IsNamedParameterTrue(string namedParameter, cNamedParameterList NamedParameters) { if (NamedParameters == null) return false; if (!NamedParameters.TryGetValue(namedParameter, out var entry)) return false; var entryValue = entry.GetValue(); cConfigRegistryHelper.ReadFromStringBoolean(entryValue, out var result); return result; } #region Customizable Section private IContainerData GetContainerDataAtIndexFromHelper(IContainerHelperClass containerHelper, int index = 0) { IContainerData output = null; try { switch (containerHelper) { case cContainerValueHelper containerValue: { string displayValue = string.Empty; cEditableValueInformationBase editableValueInformation = containerValue.EditableValueInformation; if (containerValue.RawValues.Count > index) { displayValue = _rawValueFormatter.GetDisplayValue(containerValue.RawValues[index], containerValue.DisplayType); if (editableValueInformation != null) editableValueInformation.CurrentValue = containerValue.RawValues[index]; } string maximizeValue = string.Empty; if (containerValue.RawMaximizeValues.Count > index) maximizeValue = _rawValueFormatter.GetDisplayValue(containerValue.RawMaximizeValues[index], containerValue.DisplayType); output = new cContainerValue() { DisplayValue = displayValue, MaximizeValue = maximizeValue, FontSize = containerValue.FontSize, FontWeight = containerValue.FontWeight, Description = containerValue.Description, IsEditOnly = containerValue.IsEditOnly, EditableValueInformation = editableValueInformation }; break; } case cContainerIconHelper containerIcon: { output = new cContainerIcon(enumInternIcons.none); if (containerIcon.Icons.Count > index) output = containerIcon.Icons[index]; break; } case cContainerStackPanelHelper containerStackPanel: { var outputStackPanelData = new List(); foreach (var stackPanelData in containerStackPanel.StackPanelHelperData) { try { var dataToAdd = GetContainerDataAtIndexFromHelper(stackPanelData, index); outputStackPanelData.Add(dataToAdd); } catch (Exception E) { LogException(E); } } output = new cContainerStackPanel() { StackPanelData = outputStackPanelData, Orientation = containerStackPanel.Orientation }; break; } case cContainerContentHelper containerContent: { var outputContentData = GetContainerDataAtIndexFromHelper(containerContent.Content, index); output = new cContainerPrimaryContent() { Value = outputContentData }; break; } } } catch (Exception E) { LogException(E); } return output; } private FontWeight GetFontWeightFromConfigFontWeight(enumFontWeights configFontWeight) { var output = FontWeights.Normal; try { switch (configFontWeight) { case enumFontWeights.Thin: output = FontWeights.Thin; break; case enumFontWeights.ExtraLight: output = FontWeights.ExtraLight; break; case enumFontWeights.UltraLight: output = FontWeights.UltraLight; break; case enumFontWeights.Light: output = FontWeights.Light; break; case enumFontWeights.Normal: output = FontWeights.Normal; break; case enumFontWeights.Regular: output = FontWeights.Regular; break; case enumFontWeights.Medium: output = FontWeights.Medium; break; case enumFontWeights.DemiBold: output = FontWeights.DemiBold; break; case enumFontWeights.SemiBold: output = FontWeights.SemiBold; break; case enumFontWeights.Bold: output = FontWeights.Bold; break; case enumFontWeights.ExtraBold: output = FontWeights.ExtraBold; break; case enumFontWeights.UltraBold: output = FontWeights.UltraBold; break; case enumFontWeights.Black: output = FontWeights.Black; break; case enumFontWeights.Heavy: output = FontWeights.Heavy; break; case enumFontWeights.ExtraBlack: output = FontWeights.ExtraBlack; break; case enumFontWeights.UltraBlack: output = FontWeights.UltraBlack; break; } } catch (Exception E) { LogException(E); } return output; } private IContainerData GetPlaceHolderContainerDataFromConfigElement(IStateContainerElement stateContainerElementConfig) { IContainerData output = null; try { switch (stateContainerElementConfig) { case cHealthCardStateStylable stylableStateConfig: { var fontWeight = GetFontWeightFromConfigFontWeight(stylableStateConfig.FontWeight); output = new cContainerValue() { DisplayValue = stylableStateConfig.Names.GetValue(), FontSize = stylableStateConfig.FontSize, FontWeight = fontWeight, Description = GetTitleColumnOfHealthCardState(stylableStateConfig).ContentDescription, }; break; } case cHealthCardStateIconTranslation iconTranslationStateConfig: { output = new cContainerIcon() { IconType = enumIconType.intern, IconName = "f4sd" }; break; } case cHealthCardStateStackPanel stackPanelConfig: { var orientation = Orientation.Horizontal; Enum.TryParse(stackPanelConfig.Orientation.ToString(), out orientation); var stackPanelData = new List(); foreach (var stackPanelState in stackPanelConfig.Children) { var childData = GetPlaceHolderContainerDataFromConfigElement(stackPanelState); stackPanelData.Add(childData); } output = new cContainerStackPanel() { Orientation = orientation, StackPanelData = stackPanelData }; break; } case cHealthCardStateContainerContent containerContentConfig: { var content = GetPlaceHolderContainerDataFromConfigElement(containerContentConfig.Content); output = new cContainerPrimaryContent() { Value = content }; break; } } } catch (Exception E) { LogException(E); } return output; } private IContainerHelperClass GetContainerHelperFromConfigElement(IStateContainerElement stateContainerElementConfig) { IContainerHelperClass output = null; try { switch (stateContainerElementConfig) { case cHealthCardStateStylable stylableStateConfig: { var values = GetStateValues(stylableStateConfig.DatabaseInfo, false); var display = stylableStateConfig.DisplayType; var maximingValues = GetStateValues(stylableStateConfig.MaximizedDatabaseInfo, false); var fontWeight = GetFontWeightFromConfigFontWeight(stylableStateConfig.FontWeight); cEditableValueInformationBase editableInformation = null; if (stylableStateConfig.EditInfo != null) { switch (stylableStateConfig.EditInfo) { case cStateEditableSelection edtiableSelectionInfo: var editSelectionValues = GetEditInformationSelectionValues(stylableStateConfig); editableInformation = new cEditValueInformationSelection() { DatabaseInfo = stylableStateConfig.DatabaseInfo, SelectionValues = editSelectionValues, Description = stylableStateConfig.Names.GetValue() }; break; case cStateEditableText editableTextInfo: editableInformation = new cEditValueInformationText() { DatabaseInfo = stylableStateConfig.DatabaseInfo, Description = stylableStateConfig.Names.GetValue() }; break; default: break; } } output = new cContainerValueHelper() { RawValues = values, RawMaximizeValues = maximingValues, DisplayType = cUtility.GetRawValueType(display), Description = GetTitleColumnOfHealthCardState(stylableStateConfig).ContentDescription, FontSize = stylableStateConfig.FontSize, FontWeight = fontWeight, EditableValueInformation = editableInformation, IsValueRequired = stateContainerElementConfig.IsRequired }; break; } case cHealthCardStateIconTranslation iconTranslationStateConfig: { var rawValues = GetStateValues(iconTranslationStateConfig.DatabaseInfo, false); var translation = cF4SDHealthCardConfig.GetTranslationsWithName(iconTranslationStateConfig, iconTranslationStateConfig.Translation); var icons = new List(); foreach (var rawValue in rawValues) { var iconName = "none"; enumIconType iconType = enumIconType.intern; enumHighlightColor highlightColor = enumHighlightColor.none; if (translation is cHealthCardIconTranslator iconTranslation) { var selectedTranslation = iconTranslation.IconTranslations.FirstOrDefault(tempTranslation => tempTranslation.Values.Contains(rawValue)) ?? iconTranslation.DefaultIconTranslation; if (selectedTranslation != null) { iconName = selectedTranslation.Icon.Name; iconType = selectedTranslation.Icon.IconType; switch (selectedTranslation.StateLevel) { case enumHealthCardStateLevel.Ok: highlightColor = enumHighlightColor.green; break; case enumHealthCardStateLevel.Warning: highlightColor = enumHighlightColor.orange; break; case enumHealthCardStateLevel.Error: highlightColor = enumHighlightColor.red; break; case enumHealthCardStateLevel.Info: highlightColor = enumHighlightColor.blue; break; } string toolTipText = selectedTranslation.Descriptions.GetValue(null, string.Empty); icons.Add(new cContainerIcon() { IconName = iconName, IconType = iconType, HighlightColor = highlightColor, ToolTipText = toolTipText }); } } } output = new cContainerIconHelper() { Icons = icons, IsValueRequired = stateContainerElementConfig.IsRequired }; break; } case cHealthCardStateStackPanel stackPanelConfig: { var orientation = Orientation.Horizontal; Enum.TryParse(stackPanelConfig.Orientation.ToString(), out orientation); var stackPanelData = new List(); foreach (var stackPanelState in stackPanelConfig.Children) { var childData = GetContainerHelperFromConfigElement(stackPanelState); stackPanelData.Add(childData); } output = new cContainerStackPanelHelper() { Orientation = orientation, StackPanelHelperData = stackPanelData, IsValueRequired = stateContainerElementConfig.IsRequired }; break; } case cHealthCardStateContainerContent containerContentConfig: { var content = GetContainerHelperFromConfigElement(containerContentConfig.Content); output = new cContainerContentHelper() { Content = content, IsValueRequired = stateContainerElementConfig.IsRequired || content.IsValueRequired }; break; } case cHealthCardStateEditable editableStateConfig: { cEditableValueInformationBase editableInformation = null; if (editableStateConfig.EditInfo is null) break; switch (editableStateConfig.EditInfo) { case cStateEditableSelection edtiableSelectionInfo: var editSelectionValues = GetEditInformationSelectionValues(editableStateConfig); editableInformation = new cEditValueInformationSelection() { DatabaseInfo = editableStateConfig.DatabaseInfo, SelectionValues = editSelectionValues, Description = editableStateConfig.Names.GetValue() }; break; case cStateEditableText editableTextInfo: editableInformation = new cEditValueInformationText() { DatabaseInfo = editableStateConfig.DatabaseInfo, Description = editableStateConfig.Names.GetValue() }; break; default: break; } output = new cContainerValueHelper() { RawValues = new List() { editableStateConfig.Names.GetValue() }, IsEditOnly = true, EditableValueInformation = editableInformation, IsValueRequired = stateContainerElementConfig.IsRequired }; break; } } } catch (Exception E) { LogException(E); } return output; } private List GetContainerCollectionData() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); var output = new List(); try { var customizableSectionConfig = SelectedHealthCard.CustomizableSection; if (customizableSectionConfig is null) return output; foreach (var containerConfigList in customizableSectionConfig.ContainerList) { try { if (containerConfigList is null) continue; var containerCollectionToAdd = new cContainerCollectionData() { ColumnSpan = containerConfigList.ColumnSpan }; foreach (var containerConfig in containerConfigList.StateContainers) { var containerValuesToAdd = GetContainerDataFromConfig(containerConfig); containerCollectionToAdd.AddRange(containerValuesToAdd); } output.Add(containerCollectionToAdd); } catch (Exception E) { LogException(E); } } } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return output; } #endregion public cDetailsPageData GetDetailsPageDataWithoutHeading() { cDetailsPageData output = new cDetailsPageData(); try { if (SelectedHealthCard == null) return output; output.DataProvider = dataProvider; output.WidgetData = GetWidgetsData(); output.DataHistoryList = GetDetailsPageHistoryData(); output.DataContainerCollectionList = GetContainerCollectionData(); output.MenuBarData = GetMenuBarData(); } catch (Exception E) { LogException(E); } return output; } public async Task GetDetailsPageDataAsync() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); cDetailsPageData output = new cDetailsPageData(); try { if (SelectedHealthCard == null) return output; output.DataProvider = dataProvider; output.HeadingData = await GetHeadingDataAsync(); output.WidgetData = GetWidgetsData(); output.DataHistoryList = GetDetailsPageHistoryData(); output.DataContainerCollectionList = GetContainerCollectionData(); output.MenuBarData = GetMenuBarData(); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return output; } #endregion #region NamedParameters public string ReplaceNamedParameters(string rawString, bool shouldUseHtml) { var output = rawString; try { foreach (var namedParameterEntry in dataProvider.NamedParameterEntries) { try { if (namedParameterEntry.Value is cNamedParameterEntryCopyTemplate _) continue; var parameterName = namedParameterEntry.Key; var (Title, Value) = namedParameterEntry.Value.GetTitleValuePair(); var parameterLabel = string.Format("{0}:", Title); var parameterValue = Value; if (shouldUseHtml) parameterValue = namedParameterEntry.Value.GetHtmlValue(); output = output.Replace("%" + parameterName + ".Label%", parameterLabel); output = output.Replace("%" + parameterName + ".Value%", parameterValue); } catch { } } bool found = true; while (found) { var _pos1 = output.IndexOf(".Label%"); var _pos2 = output.IndexOf(".Value%"); int _pos = -1; if (_pos1 < 0) _pos = _pos2; else if (_pos2 < 0) _pos = _pos1; else _pos = Math.Min(_pos1, _pos2); if (_pos < 0) { found = false; continue; } var _strSub = output.Substring(0, _pos); _pos1 = _strSub.LastIndexOf("%"); if (_pos1 > 0) { _strSub = output.Substring(_pos1, _pos + 7 - _pos1); output = output.Replace(_strSub, ""); } else found = false; } ; } catch (Exception E) { LogException(E); } return output; } public void UpdateNamedParameterEntries() { try { var namedParameters = cHealthCardPrerequisites.GetNamedParameters(SelectedHealthCard); foreach (var namedParameter in namedParameters) { try { if (namedParameter.Value.ParameterName == null) continue; string namedParameterTitle = namedParameter.Value.Names.GetValue(); var parameterValue = GetStateValueAt(namedParameter.Value.DatabaseInfo, 0, true); string namedParameterValue = _rawValueFormatter.GetDisplayValue(parameterValue, cUtility.GetRawValueType(namedParameter.Value.Display)); if (!dataProvider.NamedParameterEntries.ContainsKey(namedParameter.Value.ParameterName)) dataProvider.NamedParameterEntries.Add(namedParameter.Value.ParameterName, new cNamedParameterEntryPointer(dataProvider, namedParameter.Value.DatabaseInfo, cUtility.GetRawValueType(namedParameter.Value.Display)) { Title = namedParameterTitle }); } catch (Exception ex) { LogException(ex); } } 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)); } foreach (var copyTemplate in cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.CopyTemplates) { string namedParameterName = "Copy_" + copyTemplate.Key; if (dataProvider.NamedParameterEntries.ContainsKey(namedParameterName)) continue; dataProvider.NamedParameterEntries.Add(namedParameterName, new cNamedParameterEntryCopyTemplate(dataProvider, copyTemplate.Key)); } } catch (Exception E) { LogException(E); } } #endregion #endregion } public static class LoadingRawDataCriticalSection { private readonly static SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); public static async Task EnterAsync() { await _semaphore.WaitAsync(); } public static void Leave() { _semaphore.Release(); } } }