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

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