Add event-driven quick action dispatch

This commit is contained in:
Drechsler, Meik
2026-07-22 11:57:32 +02:00
parent fb45f1c42b
commit 9bd3896ba0
20 changed files with 591 additions and 139 deletions

View File

@@ -4,10 +4,14 @@ using C4IT.FASD.Security;
using C4IT.Graphics;
using C4IT.Logging;
using C4IT.MultiLanguage;
using C4IT.XML;
using F4SD.ActionConnector.Bus;
using F4SD.ActionConnector.Models;
using FasdDesktopUi.Basics;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.Models;
using FasdDesktopUi.Basics.UiActions.NativeActions;
using FasdDesktopUi.Pages.CustomMessageBox;
using FasdDesktopUi.Pages.PhoneSettingsPage;
using FasdDesktopUi.Pages.SearchPage;
@@ -45,6 +49,8 @@ namespace FasdDesktopUi
private TileScope? _pendingTicketOverviewScope;
#endregion
private ActionBus _actionBus;
private async void Application_Startup(object sender, StartupEventArgs e)
{
@@ -62,7 +68,7 @@ namespace FasdDesktopUi
Thread.Sleep(100);
}
Console.WriteLine("Debugger attached");
*/
*/
Assembly assembly = Assembly.GetExecutingAssembly();
var ProductName = FileVersionInfo.GetVersionInfo(assembly.Location).ProductName;
var attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
@@ -127,7 +133,24 @@ namespace FasdDesktopUi
InitializeNotifyIcon();
//CustomMessageBox.ShowCustomContent("Close case", enumHealthCardStateLevel.None, null, true, new CloseCaseDialogWithTicket());
try
{
//_actionBus = new ActionBus(new ActionBusOptions()
//{
// ConfigRootElement = cXmlParser.OpenXmlDocument(new List<cXmlFileLocation>() { new cXmlFileLocation()
// {
// LocationType = cXmlFileLocation.enumXmlLocationType.StringContent,
// StringContent = string.Empty
// } }, out cXmlParser parser, ExternalCommunicationConfiguration.ConfigRootElement),
// Parser = parser,
// QuickActionExecutor = QuickActionExecutor.RunAction
//});
//_actionBus.Start();
}
catch (Exception ex)
{
LogException(ex);
}
await cAppStartUp.StartAsync(e.Args);
notifyIcon.Visible = true;
@@ -491,19 +514,19 @@ namespace FasdDesktopUi
}
}
#endregion
#endregion
private async void Application_Exit(object sender, ExitEventArgs e)
{
cF4sdUserInfo userInfo = null;
ConfiguredTaskAwaitable? closeUserSessionTask = null;
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
{
userInfo = cFasdCockpitCommunicationBase.CockpitUserInfo;
}
if (userInfo?.Id.Equals(Guid.Empty) is false)
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
{
closeUserSessionTask = cFasdCockpitCommunicationBase.Instance?.CloseUserSession(cFasdCockpitConfig.SessionId).ConfigureAwait(false);
userInfo = cFasdCockpitCommunicationBase.CockpitUserInfo;
}
if (userInfo?.Id.Equals(Guid.Empty) is false)
{
closeUserSessionTask = cFasdCockpitCommunicationBase.Instance?.CloseUserSession(cFasdCockpitConfig.SessionId).ConfigureAwait(false);
}
if (cFasdCockpitCommunicationBase.Instance != null)
@@ -545,6 +568,8 @@ namespace FasdDesktopUi
}
catch { }
_actionBus?.Stop();
if (closeUserSessionTask is ConfiguredTaskAwaitable _t)
await _t;
}

View File

@@ -1,4 +1,5 @@
using System;
using FasdDesktopUi.Basics.UiActions.NativeActions;
using System;
using System.Collections.Generic;
namespace FasdDesktopUi.Basics.Services.SupportCase.Processors
@@ -12,6 +13,7 @@ namespace FasdDesktopUi.Basics.Services.SupportCase.Processors
if (!_supportCaseProccesors.ContainsKey(id))
_supportCaseProccesors.Add(id, new SupportCaseProcessor());
QuickActionExecutor.SetSupportCaseProcessor(_supportCaseProccesors[id]);
return _supportCaseProccesors[id];
}
}

View File

@@ -1,37 +1,38 @@
using System;
using C4IT.F4SD.SupportCaseProtocoll.Models;
using C4IT.FASD.Base;
using C4IT.FASD.Cockpit.Communication;
using C4IT.Logging;
using C4IT.MultiLanguage;
using F4SD.ActionConnector.Bus;
using F4SD.ActionConnector.Events;
using F4SD.ActionConnector.Payloads;
using F4SD.Gamification;
using F4SD.Gamification.Services;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.ProtocollService;
using FasdDesktopUi.Basics.Services.RelationService;
using FasdDesktopUi.Basics.Services.SupportCase;
using FasdDesktopUi.Basics.Services.SupportCase.Controllers;
using FasdDesktopUi.Basics.Services.SupportCase.Processors;
using FasdDesktopUi.Basics.UserControls;
using FasdDesktopUi.Config;
using FasdDesktopUi.Pages;
using FasdDesktopUi.Pages.CustomMessageBox;
using FasdDesktopUi.Pages.SearchPage;
using FasdDesktopUi.Pages.TicketCompletion;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Documents;
using System.Linq;
using System.Windows.Input;
using System.Diagnostics;
using C4IT.FASD.Base;
using C4IT.Logging;
using C4IT.FASD.Cockpit.Communication;
using C4IT.MultiLanguage;
using static C4IT.Logging.cLogManager;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UserControls;
using FasdDesktopUi.Pages;
using FasdDesktopUi.Pages.CustomMessageBox;
using FasdDesktopUi.Config;
using FasdDesktopUi.Pages.SearchPage;
using FasdDesktopUi.Pages.TicketCompletion;
using Newtonsoft.Json;
using FasdDesktopUi.Basics.Services.ProtocollService;
using FasdDesktopUi.Basics.Services.SupportCase;
using FasdDesktopUi.Basics.Services.RelationService;
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
{
@@ -303,6 +304,8 @@ namespace FasdDesktopUi.Basics
detailsPage?.EndPause();
ActionConnectorEvents.RaiseCaseClosed(this, new CaseClosedPayload() { ClosedAt = DateTime.UtcNow });
List<Task> tasks = new List<Task>();
tasks.Add(DirectConnectionHelper.DirectConnectionStopAsync());

View File

@@ -0,0 +1,71 @@
using C4IT.FASD.Base;
using F4SD.ActionConnector.Execution;
using F4SD.ActionConnector.Models;
using F4SD.ActionConnector.Payloads;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.SupportCase.Controllers;
using FasdDesktopUi.Basics.Services.SupportCase.Processors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UiActions.NativeActions
{
internal static class QuickActionExecutor
{
private static ISupportCaseProcessor _supportCaseProcessor;
internal static void SetSupportCaseProcessor(ISupportCaseProcessor supportCaseProcessor)
{
_supportCaseProcessor = supportCaseProcessor ?? throw new ArgumentNullException(nameof(supportCaseProcessor));
}
internal static async Task<ActionResult> RunAction(QuickActionRequest quickActionRequest)
{
try
{
if (_supportCaseProcessor is null)
return ActionResult.Fail(quickActionRequest.ActionId, "No valid SupportCase processor was found.");
if (!(quickActionRequest.Context.Payload is CaseClosedPayload payload))
return ActionResult.Fail(quickActionRequest.ActionId, $"Payload is not of type '{typeof(CaseClosedPayload)}'. It is of type '{quickActionRequest.Context.Payload.GetType()}'");
cMenuDataBase menuData = MenuDataFactory.GetByName(quickActionRequest.QuickActionRef, _supportCaseProcessor.SupportCaseDataProviderArtifact.NamedParameterEntries, _supportCaseProcessor.SupportCaseDataProviderArtifact.CaseRelations.Select(r => r.Key));
// Till there is a clear picture of what object belongs to a case and what doesn't
// we do not want to make remote Quick Actions available
if (menuData is null || !(menuData.UiAction is cUiLocalQuickAction quickAction))
{
LogEntry($"'{quickActionRequest.QuickActionRef}' is no valid Local QuickAction and was therefore skipped.", C4IT.Logging.LogLevels.Error);
return ActionResult.Skip(quickActionRequest.ActionId);
}
await quickAction.RunUiActionAsync(null, null, false, _supportCaseProcessor.SupportCaseDataProviderArtifact);
await quickAction.ProcessActionAsync(CancellationToken.None, GetParameterDictionaryFrom(quickActionRequest.Parameters));
return ActionResult.Ok(quickActionRequest.ActionId);
}
catch (Exception ex)
{
LogException(ex);
return ActionResult.Fail(quickActionRequest.ActionId, ex.Message);
}
}
private static Dictionary<cAdjustableParameter, object> GetParameterDictionaryFrom(IDictionary<string, object> requestParameters)
{
try
{
return requestParameters.ToDictionary(p => new cAdjustableParameterString() { ParameterName = p.Key } as cAdjustableParameter, p => p.Value);
}
catch (Exception ex)
{
LogException(ex);
return new Dictionary<cAdjustableParameter, object>();
}
}
}
}

View File

@@ -137,7 +137,7 @@ namespace FasdDesktopUi.Basics.UiActions
quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.finished });
else
{
StatusMonitor.QuickActionOutputs.Add(ResultRevision.Output);
StatusMonitor?.QuickActionOutputs?.Add(ResultRevision.Output);
quickActionOutput = cQuickActionOutput.GetQuickActionOutput(ResultRevision.Output, DataProvider);
}
@@ -152,7 +152,7 @@ namespace FasdDesktopUi.Basics.UiActions
cMultiLanguageSupport.CurrentLanguage = tempLang;
}
cQuickActionCopyData copyData = QuickActionProtocollEntryOutput.GetCopyData(LocalQuickAction, DataProvider, false, protocollOutput, StatusMonitor.MeasureValues);
cQuickActionCopyData copyData = QuickActionProtocollEntryOutput.GetCopyData(LocalQuickAction, DataProvider, false, protocollOutput, StatusMonitor?.MeasureValues);
QuickActionProtocollEntry protocollEntry = QuickActionProtocollEntryOutput.GetQuickActionProtocollEntry(LocalQuickAction, copyData);
F4SDProtocoll.Instance.Add(protocollEntry);
@@ -192,7 +192,7 @@ namespace FasdDesktopUi.Basics.UiActions
cMultiLanguageSupport.CurrentLanguage = tempLang;
}
cQuickActionCopyData copyData = QuickActionProtocollEntryOutput.GetCopyData(LocalQuickAction, DataProvider, false, protocollOutput, StatusMonitor.MeasureValues);
cQuickActionCopyData copyData = QuickActionProtocollEntryOutput.GetCopyData(LocalQuickAction, DataProvider, false, protocollOutput, StatusMonitor?.MeasureValues);
QuickActionProtocollEntry protocollEntry = QuickActionProtocollEntryOutput.GetQuickActionProtocollEntry(LocalQuickAction, copyData);
F4SDProtocoll.Instance.Add(protocollEntry);

View File

@@ -152,8 +152,7 @@
Background="{DynamicResource BackgroundColor.DetailsPage.Widget.Title}"
SpellCheck.IsEnabled="True"
SelectionChanged="NotepadRichTextBox_SelectionChanged"
IsVisibleChanged="NotepadRichTextBox_IsVisibleChanged"
GotKeyboardFocus="NotepadRichTextBox_GotKeyboardFocus">
IsVisibleChanged="NotepadRichTextBox_IsVisibleChanged">
<RichTextBox.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius"

View File

@@ -155,29 +155,6 @@ namespace FasdDesktopUi.Basics.UserControls
#region Methods
private void NotepadRichTextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
try
{
if (_dataProvider is null)
return;
if (_dataProvider?.CaseNotes?.Parent is RichTextBox parentBox)
parentBox.Document = new FlowDocument();
if (!(sender is RichTextBox senderElement))
return;
senderElement.Document = _dataProvider.CaseNotes;
senderElement.CaretPosition = senderElement.CaretPosition.DocumentEnd;
}
catch (Exception E)
{
LogException(E);
}
}
private async void NotepadRichTextBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
try
@@ -185,11 +162,15 @@ namespace FasdDesktopUi.Basics.UserControls
if (!(e.NewValue is bool isVisible && isVisible))
return;
await Task.Delay(50);
NotepadRichTextBox.Focus();
Keyboard.Focus(NotepadRichTextBox);
if (!(sender is RichTextBox senderElement))
return;
NotepadRichTextBox_GotKeyboardFocus(sender, null);
senderElement.Document = _dataProvider.CaseNotes;
senderElement.CaretPosition = senderElement.CaretPosition.DocumentEnd;
await Task.Delay(50);
senderElement.Focus();
Keyboard.Focus(senderElement);
}
catch (Exception E)
{

View File

@@ -252,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\QuickActionExecutor.cs" />
<Compile Include="Basics\UiActions\NativeActions\RemoteConnectionAction.cs" />
<Compile Include="Basics\UiActions\UiCopyDetailsTableContent.cs" />
<Compile Include="Basics\UiActions\UiDummyQuickAction.cs" />
@@ -1017,6 +1018,10 @@
<EmbeddedResource Include="Config\LanguageDefinitions.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\F4SD-ActionConnector\F4SD-ActionConnector.csproj">
<Project>{887c6721-b9f3-c83a-3d55-5e684ca19592}</Project>
<Name>F4SD-ActionConnector</Name>
</ProjectReference>
<ProjectReference Include="..\F4SD-AdaptableIcon\F4SD-AdaptableIcon.csproj">
<Project>{bab63a6a-1524-435d-9f96-7a30b6ee0624}</Project>
<Name>F4SD-AdaptableIcon</Name>