279 lines
12 KiB
C#
279 lines
12 KiB
C#
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;
|
|
|
|
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;
|
|
}
|
|
}
|