Compare commits
21 Commits
9f2c3fefc1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffcfc85a4e | ||
|
|
2d3460574e | ||
|
|
bdff275da9 | ||
|
|
bb5d7c1d2a | ||
|
|
9bd3896ba0 | ||
|
|
fb45f1c42b | ||
|
|
1a3bef9eeb | ||
|
|
21e9b85be7 | ||
|
|
30cc7a0482 | ||
|
|
4ed75c6e82 | ||
|
|
791e53062e | ||
|
|
b88b325d02 | ||
|
|
2fbf2e2d2d | ||
|
|
62a5c97cbd | ||
|
|
0fef3ad49c | ||
|
|
1db0da9a40 | ||
|
|
7ea13f60a7 | ||
|
|
b3520f8865 | ||
|
|
997dcee78f | ||
|
|
0b52999b1d | ||
|
|
bbedbf71c8 |
159
F4SD-ActionConnector/Bus/ActionBus.cs
Normal file
159
F4SD-ActionConnector/Bus/ActionBus.cs
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
using F4SD.ActionConnector.Events;
|
||||||
|
using F4SD.ActionConnector.Execution;
|
||||||
|
using F4SD.ActionConnector.Models;
|
||||||
|
using F4SD.ActionConnector.Payloads;
|
||||||
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Bus
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Entry point for the ActionConnector.
|
||||||
|
/// Subscribes to <see cref="ActionConnectorEvents"/>, reads the configuration once,
|
||||||
|
/// and dispatches actions whenever a trigger event fires.
|
||||||
|
///
|
||||||
|
/// Usage from the host application:
|
||||||
|
/// <code>
|
||||||
|
/// var bus = new ActionBus(new ActionBusOptions
|
||||||
|
/// {
|
||||||
|
/// ConfigurationFilePath = @"C:\Config\F4SD-ExternalCommunication-Configuration.xml",
|
||||||
|
/// QuickActionExecutor = async request =>
|
||||||
|
/// {
|
||||||
|
/// await myJiraClient.CreateTicketAsync(request.QuickActionRef, request.Parameters);
|
||||||
|
/// return ActionResult.Ok(request.ActionId);
|
||||||
|
/// }
|
||||||
|
/// });
|
||||||
|
///
|
||||||
|
/// bus.Start();
|
||||||
|
/// // later:
|
||||||
|
/// bus.Stop();
|
||||||
|
/// </code>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ActionBus : IDisposable
|
||||||
|
{
|
||||||
|
private readonly ActionBusOptions _options;
|
||||||
|
private readonly ActionDispatcher _dispatcher;
|
||||||
|
private ExternalCommunicationConfiguration _configuration;
|
||||||
|
private bool _running;
|
||||||
|
|
||||||
|
public ActionBus(ActionBusOptions options)
|
||||||
|
{
|
||||||
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
|
_dispatcher = new ActionDispatcher(options.QuickActionExecutor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads the configuration and subscribes to all trigger events.
|
||||||
|
/// Call once during application startup.
|
||||||
|
/// </summary>
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
|
LogMethodBegin(CM);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_configuration = new ExternalCommunicationConfiguration();
|
||||||
|
_configuration.Initiate(_options.ConfigRootElement, _options.Parser);
|
||||||
|
|
||||||
|
ActionConnectorEvents.CaseClosed += OnCaseClosed;
|
||||||
|
ActionConnectorEvents.CaseCreated += OnCaseCreated;
|
||||||
|
ActionConnectorEvents.ApplicationStartup += OnApplicationStartup;
|
||||||
|
|
||||||
|
_running = true;
|
||||||
|
LogEntry("ActionBus started.", C4IT.Logging.LogLevels.Info);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
LogMethodEnd(CM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unsubscribes from all trigger events.
|
||||||
|
/// Call during application shutdown.
|
||||||
|
/// </summary>
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
ActionConnectorEvents.CaseClosed -= OnCaseClosed;
|
||||||
|
ActionConnectorEvents.CaseCreated -= OnCaseCreated;
|
||||||
|
ActionConnectorEvents.ApplicationStartup -= OnApplicationStartup;
|
||||||
|
|
||||||
|
_running = false;
|
||||||
|
LogEntry("ActionBus stopped.", C4IT.Logging.LogLevels.Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() => Stop();
|
||||||
|
|
||||||
|
// ──────────────────────────────────────────────────────────────────────────
|
||||||
|
// Event handlers — each one creates a typed ActionContext and fires dispatch
|
||||||
|
// ──────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void OnCaseClosed(object sender, TriggerEventArgs<CaseClosedPayload> args)
|
||||||
|
=> DispatchTrigger(TriggerEvent.CaseClosed, args.Payload, sender);
|
||||||
|
|
||||||
|
private void OnCaseCreated(object sender, TriggerEventArgs<CaseCreatedPayload> args)
|
||||||
|
=> DispatchTrigger(TriggerEvent.CaseCreated, args.Payload, sender);
|
||||||
|
|
||||||
|
private void OnApplicationStartup(object sender, TriggerEventArgs<ApplicationStartupPayload> args)
|
||||||
|
=> DispatchTrigger(TriggerEvent.ApplicationStartup, args.Payload, sender);
|
||||||
|
|
||||||
|
// ──────────────────────────────────────────────────────────────────────────
|
||||||
|
// Core dispatch — fire-and-forget wrapper that surfaces results via events
|
||||||
|
// ──────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private void DispatchTrigger(TriggerEvent triggerEvent, PayloadBase payload, object sender)
|
||||||
|
{
|
||||||
|
if (!_running) return;
|
||||||
|
if (!_configuration.Triggers.TryGetValue(triggerEvent, out Trigger trigger)) return;
|
||||||
|
|
||||||
|
// Run async dispatch on the thread pool; do not block the caller.
|
||||||
|
Task.Run(() => DispatchActionsAsync(trigger.Actions, triggerEvent, payload, sender));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DispatchActionsAsync(
|
||||||
|
IDictionary<string, ActionDefinitionBase> actions,
|
||||||
|
TriggerEvent triggerEvent,
|
||||||
|
PayloadBase payload,
|
||||||
|
object sender)
|
||||||
|
{
|
||||||
|
foreach (var pair in actions)
|
||||||
|
{
|
||||||
|
ActionDefinitionBase action = pair.Value;
|
||||||
|
|
||||||
|
var context = new ActionContext
|
||||||
|
{
|
||||||
|
TriggerEvent = triggerEvent,
|
||||||
|
AwaitResult = action.AwaitResult,
|
||||||
|
Payload = payload,
|
||||||
|
};
|
||||||
|
|
||||||
|
ActionResult result = await ExecuteSafeAsync(action, context);
|
||||||
|
|
||||||
|
ActionConnectorEvents.RaiseActionCompleted(
|
||||||
|
sender,
|
||||||
|
new ActionCompletedEventArgs(result, context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ActionResult> ExecuteSafeAsync(ActionDefinitionBase action, ActionContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _dispatcher.DispatchAsync(action, context);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
return ActionResult.Fail(action.Id, ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
F4SD-ActionConnector/Bus/ActionBusOptions.cs
Normal file
23
F4SD-ActionConnector/Bus/ActionBusOptions.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
using C4IT.XML;
|
||||||
|
using F4SD.ActionConnector.Execution;
|
||||||
|
using F4SD.ActionConnector.Models;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Bus
|
||||||
|
{
|
||||||
|
public sealed class ActionBusOptions
|
||||||
|
{
|
||||||
|
public XmlElement ConfigRootElement { get; set; }
|
||||||
|
public cXmlParser Parser { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called for every QuickAction that fires.
|
||||||
|
/// Template variables in <see cref="QuickActionRequest.Parameters"/> are already
|
||||||
|
/// resolved against the event payload before this delegate is invoked.
|
||||||
|
/// Must be set when any QuickAction is configured.
|
||||||
|
/// </summary>
|
||||||
|
public Func<QuickActionRequest, Task<ActionResult>> QuickActionExecutor { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
9
F4SD-ActionConnector/Enumerations/ActionResultStatus.cs
Normal file
9
F4SD-ActionConnector/Enumerations/ActionResultStatus.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace F4SD.ActionConnector.Enumerations
|
||||||
|
{
|
||||||
|
public enum ActionResultStatus
|
||||||
|
{
|
||||||
|
Success,
|
||||||
|
Failure,
|
||||||
|
Skipped
|
||||||
|
}
|
||||||
|
}
|
||||||
10
F4SD-ActionConnector/Enumerations/ActionType.cs
Normal file
10
F4SD-ActionConnector/Enumerations/ActionType.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace F4SD.ActionConnector.Enumerations
|
||||||
|
{
|
||||||
|
public enum ActionType
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
QuickAction,
|
||||||
|
HttpCall,
|
||||||
|
Webhook,
|
||||||
|
}
|
||||||
|
}
|
||||||
10
F4SD-ActionConnector/Enumerations/TriggerEvent.cs
Normal file
10
F4SD-ActionConnector/Enumerations/TriggerEvent.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace F4SD.ActionConnector.Enumerations
|
||||||
|
{
|
||||||
|
public enum TriggerEvent
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
ApplicationStartup,
|
||||||
|
CaseClosed,
|
||||||
|
CaseCreated,
|
||||||
|
}
|
||||||
|
}
|
||||||
21
F4SD-ActionConnector/Events/ActionCompletedEventArgs.cs
Normal file
21
F4SD-ActionConnector/Events/ActionCompletedEventArgs.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using F4SD.ActionConnector.Models;
|
||||||
|
using F4SD.ActionConnector.Payloads;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Raised after a sync action finishes. Carries the result for Cockpit integration.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ActionCompletedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public ActionResult Result { get; }
|
||||||
|
public ActionContext Context { get; }
|
||||||
|
|
||||||
|
public ActionCompletedEventArgs(ActionResult result, ActionContext context)
|
||||||
|
{
|
||||||
|
Result = result;
|
||||||
|
Context = context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
F4SD-ActionConnector/Events/ActionConnectorEvents.cs
Normal file
40
F4SD-ActionConnector/Events/ActionConnectorEvents.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using F4SD.ActionConnector.Payloads;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Static event bus. F4SD calls the methods after a business event occurs.
|
||||||
|
/// The connector engine subscribes to the corresponding events and dispatches configured actions.
|
||||||
|
/// </summary>
|
||||||
|
public static class ActionConnectorEvents
|
||||||
|
{
|
||||||
|
/// <summary>Raised when a support case is closed.</summary>
|
||||||
|
public static event EventHandler<TriggerEventArgs<CaseClosedPayload>> CaseClosed;
|
||||||
|
|
||||||
|
/// <summary>Raised when a new support case is created.</summary>
|
||||||
|
public static event EventHandler<TriggerEventArgs<CaseCreatedPayload>> CaseCreated;
|
||||||
|
|
||||||
|
/// <summary>Raised once during application startup, after configuration is loaded.</summary>
|
||||||
|
public static event EventHandler<TriggerEventArgs<ApplicationStartupPayload>> ApplicationStartup;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised after every sync action completes. The Cockpit Client subscribes here
|
||||||
|
/// to display results without coupling to specific trigger types.
|
||||||
|
/// </summary>
|
||||||
|
public static event EventHandler<ActionCompletedEventArgs> ActionCompleted;
|
||||||
|
|
||||||
|
|
||||||
|
public static void RaiseCaseClosed(object sender, CaseClosedPayload payload)
|
||||||
|
=> CaseClosed?.Invoke(sender, new TriggerEventArgs<CaseClosedPayload>(payload));
|
||||||
|
|
||||||
|
public static void RaiseCaseCreated(object sender, CaseCreatedPayload payload)
|
||||||
|
=> CaseCreated?.Invoke(sender, new TriggerEventArgs<CaseCreatedPayload>(payload));
|
||||||
|
|
||||||
|
public static void RaiseApplicationStartup(object sender, ApplicationStartupPayload payload)
|
||||||
|
=> ApplicationStartup?.Invoke(sender, new TriggerEventArgs<ApplicationStartupPayload>(payload));
|
||||||
|
|
||||||
|
public static void RaiseActionCompleted(object sender, ActionCompletedEventArgs args)
|
||||||
|
=> ActionCompleted?.Invoke(sender, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
F4SD-ActionConnector/Events/TriggerEventArgs.cs
Normal file
15
F4SD-ActionConnector/Events/TriggerEventArgs.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using F4SD.ActionConnector.Payloads;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Events
|
||||||
|
{
|
||||||
|
public sealed class TriggerEventArgs<TPayload> : EventArgs where TPayload : PayloadBase
|
||||||
|
{
|
||||||
|
public TPayload Payload { get; }
|
||||||
|
|
||||||
|
public TriggerEventArgs(TPayload payload)
|
||||||
|
{
|
||||||
|
Payload = payload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
F4SD-ActionConnector/Execution/ActionDispatcher.cs
Normal file
62
F4SD-ActionConnector/Execution/ActionDispatcher.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
using F4SD.ActionConnector.Models;
|
||||||
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Execution
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Routes a single action definition to the correct executor based on its <see cref="ActionType"/>.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class ActionDispatcher
|
||||||
|
{
|
||||||
|
private readonly Func<QuickActionRequest, Task<ActionResult>> _quickActionExecutor;
|
||||||
|
|
||||||
|
internal ActionDispatcher(Func<QuickActionRequest, Task<ActionResult>> quickActionExecutor)
|
||||||
|
{
|
||||||
|
_quickActionExecutor = quickActionExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task<ActionResult> DispatchAsync(ActionDefinitionBase action, ActionContext context)
|
||||||
|
{
|
||||||
|
if (!action.IsEnabled)
|
||||||
|
return ActionResult.Skip(action.Id);
|
||||||
|
|
||||||
|
switch (action.Type)
|
||||||
|
{
|
||||||
|
case ActionType.QuickAction:
|
||||||
|
return await ExecuteQuickActionAsync((QuickActionDefinition)action, context);
|
||||||
|
|
||||||
|
case ActionType.HttpCall:
|
||||||
|
case ActionType.Webhook:
|
||||||
|
throw new NotImplementedException(
|
||||||
|
$"ActionType '{action.Type}' is not yet implemented.");
|
||||||
|
|
||||||
|
default:
|
||||||
|
LogEntry($"ActionDispatcher: unknown ActionType '{action.Type}' for action '{action.Id}'.",
|
||||||
|
C4IT.Logging.LogLevels.Warning);
|
||||||
|
return ActionResult.Skip(action.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ActionResult> ExecuteQuickActionAsync(QuickActionDefinition definition, ActionContext context)
|
||||||
|
{
|
||||||
|
if (_quickActionExecutor == null)
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"A QuickAction ('{definition.Id}') was triggered but no {nameof(Bus.ActionBusOptions.QuickActionExecutor)} was registered.");
|
||||||
|
|
||||||
|
var resolvedParameters = PayloadVariableResolver.Resolve(definition.Parameters, context.Payload);
|
||||||
|
|
||||||
|
var request = new QuickActionRequest
|
||||||
|
{
|
||||||
|
ActionId = definition.Id,
|
||||||
|
QuickActionRef = definition.QuickActionRef,
|
||||||
|
Parameters = resolvedParameters,
|
||||||
|
Context = context,
|
||||||
|
};
|
||||||
|
|
||||||
|
return await _quickActionExecutor(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
94
F4SD-ActionConnector/Execution/PayloadVariableResolver.cs
Normal file
94
F4SD-ActionConnector/Execution/PayloadVariableResolver.cs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using F4SD.ActionConnector.Payloads;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Execution
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Resolves template variables such as {{Case.Id}} or {{Case.ClosedAt:yyyy-MM-ddTHH:mm:ssZ}}
|
||||||
|
/// against a payload object.
|
||||||
|
///
|
||||||
|
/// Variable format: {{ObjectName.PropertyName[:FormatSpecifier]}}
|
||||||
|
/// </summary>
|
||||||
|
internal static class PayloadVariableResolver
|
||||||
|
{
|
||||||
|
private static readonly Regex VariablePattern =
|
||||||
|
new Regex(@"\{\{(?<obj>[^.}]+)\.(?<prop>[^:}]+)(?::(?<fmt>[^}]+))?\}\}",
|
||||||
|
RegexOptions.Compiled);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a new dictionary with every value in <paramref name="rawParameters"/> having
|
||||||
|
/// its template variables replaced by the corresponding payload property values.
|
||||||
|
/// Pure single-variable templates (e.g. <c>{{Case.ClosedAt}}</c>) yield the raw typed
|
||||||
|
/// object; mixed or formatted templates yield a resolved string.
|
||||||
|
/// </summary>
|
||||||
|
internal static IDictionary<string, object> Resolve(
|
||||||
|
IDictionary<string, string> rawParameters,
|
||||||
|
PayloadBase payload)
|
||||||
|
{
|
||||||
|
var resolved = new Dictionary<string, object>(rawParameters.Count);
|
||||||
|
|
||||||
|
foreach (var pair in rawParameters)
|
||||||
|
resolved[pair.Key] = ResolveValue(pair.Value, payload);
|
||||||
|
|
||||||
|
return resolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object ResolveValue(string template, PayloadBase payload)
|
||||||
|
{
|
||||||
|
var match = VariablePattern.Match(template);
|
||||||
|
|
||||||
|
// Pure single variable with no format specifier → return raw object
|
||||||
|
if (match.Success && match.Value == template && !match.Groups["fmt"].Success)
|
||||||
|
return ResolveRawProperty(match, payload);
|
||||||
|
|
||||||
|
// Mixed template, literal, or explicit format specifier → return resolved string
|
||||||
|
return ResolveString(template, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object ResolveRawProperty(Match match, PayloadBase payload)
|
||||||
|
{
|
||||||
|
string propertyName = match.Groups["prop"].Value;
|
||||||
|
|
||||||
|
PropertyInfo property = payload.GetType().GetProperty(
|
||||||
|
propertyName,
|
||||||
|
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||||
|
|
||||||
|
if (property == null)
|
||||||
|
return match.Value;
|
||||||
|
|
||||||
|
return property.GetValue(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveString(string template, PayloadBase payload)
|
||||||
|
{
|
||||||
|
return VariablePattern.Replace(template, match => ResolveMatch(match, payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveMatch(Match match, PayloadBase payload)
|
||||||
|
{
|
||||||
|
string propertyName = match.Groups["prop"].Value;
|
||||||
|
string formatSpecifier = match.Groups["fmt"].Success ? match.Groups["fmt"].Value : null;
|
||||||
|
|
||||||
|
PropertyInfo property = payload.GetType().GetProperty(
|
||||||
|
propertyName,
|
||||||
|
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||||
|
|
||||||
|
if (property == null)
|
||||||
|
return match.Value;
|
||||||
|
|
||||||
|
object value = property.GetValue(payload);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
if (formatSpecifier != null && value is IFormattable formattable)
|
||||||
|
return formattable.ToString(formatSpecifier, CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
return value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
F4SD-ActionConnector/Execution/QuickActionRequest.cs
Normal file
29
F4SD-ActionConnector/Execution/QuickActionRequest.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using F4SD.ActionConnector.Models;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Execution
|
||||||
|
{
|
||||||
|
public sealed class QuickActionRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Matches <see cref="QuickActionDefinition.Id"/> from the configuration.
|
||||||
|
/// </summary>
|
||||||
|
public string ActionId { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the Quick Action to invoke, e.g. "Document case in JIRA".
|
||||||
|
/// </summary>
|
||||||
|
public string QuickActionRef { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Template variables resolved against the event payload.
|
||||||
|
/// Values are the raw payload values; callers are responsible for casting.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<string, object> Parameters { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Full context of the triggering event.
|
||||||
|
/// </summary>
|
||||||
|
public ActionContext Context { get; internal set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
16
F4SD-ActionConnector/F4SD-ActionConnector.csproj
Normal file
16
F4SD-ActionConnector/F4SD-ActionConnector.csproj
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<RootNamespace>F4SD.ActionConnector</RootNamespace>
|
||||||
|
<AssemblyName>F4SD-ActionConnector</AssemblyName>
|
||||||
|
<Nullable>disable</Nullable>
|
||||||
|
<LangVersion>7.3</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\F4SD-Logging\F4SD-Logging.csproj" />
|
||||||
|
<ProjectReference Include="..\FasdCockpitBase\F4SD-Cockpit-Client-Base.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
12
F4SD-ActionConnector/Models/ActionContext.cs
Normal file
12
F4SD-ActionConnector/Models/ActionContext.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
using F4SD.ActionConnector.Payloads;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Models
|
||||||
|
{
|
||||||
|
public sealed class ActionContext
|
||||||
|
{
|
||||||
|
public TriggerEvent TriggerEvent { get; internal set; }
|
||||||
|
public bool AwaitResult { get; internal set; }
|
||||||
|
public PayloadBase Payload { get; internal set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
38
F4SD-ActionConnector/Models/ActionDefinitionBase.cs
Normal file
38
F4SD-ActionConnector/Models/ActionDefinitionBase.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using C4IT.XML;
|
||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
using System;
|
||||||
|
using System.Xml;
|
||||||
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Models
|
||||||
|
{
|
||||||
|
public abstract class ActionDefinitionBase
|
||||||
|
{
|
||||||
|
public string Id { get; internal set; }
|
||||||
|
public abstract ActionType Type { get; }
|
||||||
|
public bool AwaitResult { get; internal set; }
|
||||||
|
public bool IsEnabled { get; internal set; }
|
||||||
|
public string Description { get; internal set; }
|
||||||
|
public bool IsValid { get; private protected set; }
|
||||||
|
|
||||||
|
protected ActionDefinitionBase(XmlElement xNode, cXmlParser parser)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Id = cXmlParser.GetStringFromXmlAttribute(xNode, "Id");
|
||||||
|
AwaitResult = cXmlParser.GetBoolFromXmlAttribute(xNode, "AwaitResult");
|
||||||
|
IsEnabled = cXmlParser.GetBoolFromXmlAttribute(xNode, "IsEnabled");
|
||||||
|
|
||||||
|
XmlNode descriptionNode = xNode.SelectSingleNode("Description");
|
||||||
|
if (descriptionNode != null)
|
||||||
|
Description = cXmlParser.GetInnerTextFromXmlElement(descriptionNode);
|
||||||
|
|
||||||
|
IsValid = true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
F4SD-ActionConnector/Models/ActionResult.cs
Normal file
41
F4SD-ActionConnector/Models/ActionResult.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Models
|
||||||
|
{
|
||||||
|
public sealed class ActionResult
|
||||||
|
{
|
||||||
|
public string ActionId { get; private set; }
|
||||||
|
public ActionResultStatus Status { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HTTP status code for HttpCall actions; null for other types.
|
||||||
|
/// </summary>
|
||||||
|
public int? HttpStatusCode { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raw response body (HttpCall) or serialized output (QuickAction).
|
||||||
|
/// </summary>
|
||||||
|
public string RawResponse { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Named fields extracted from the response via jsonPath mappings.
|
||||||
|
/// Populated when DisplayInCockpit is true.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<string, string> MappedFields { get; private set; } = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Human-readable error message; set when Status is Failure.
|
||||||
|
/// </summary>
|
||||||
|
public string ErrorMessage { get; private set; }
|
||||||
|
|
||||||
|
public static ActionResult Ok(string actionId, string rawResponse = null)
|
||||||
|
=> new ActionResult { ActionId = actionId, Status = ActionResultStatus.Success, RawResponse = rawResponse };
|
||||||
|
|
||||||
|
public static ActionResult Fail(string actionId, string errorMessage)
|
||||||
|
=> new ActionResult { ActionId = actionId, Status = ActionResultStatus.Failure, ErrorMessage = errorMessage };
|
||||||
|
|
||||||
|
public static ActionResult Skip(string actionId)
|
||||||
|
=> new ActionResult { ActionId = actionId, Status = ActionResultStatus.Skipped };
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
using C4IT.XML;
|
||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Xml;
|
||||||
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Models
|
||||||
|
{
|
||||||
|
public class ExternalCommunicationConfiguration
|
||||||
|
{
|
||||||
|
private const string FileNameConfig = "F4SD-ExternalCommunication-Configuration.xml";
|
||||||
|
private const string FileNameConfigSchema = "F4SD-ExternalCommunication-Configuration.xsd";
|
||||||
|
public const string ConfigRootElement = "F4SD-ExternalCommunication-Configuration";
|
||||||
|
|
||||||
|
public IDictionary<TriggerEvent, Trigger> Triggers { get; } = new Dictionary<TriggerEvent, Trigger>();
|
||||||
|
|
||||||
|
|
||||||
|
private const string TriggersNodeName = "Triggers";
|
||||||
|
private const string TriggerNodeName = "Trigger";
|
||||||
|
|
||||||
|
public void Initiate(XmlElement rootElement, cXmlParser parser)
|
||||||
|
{
|
||||||
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
|
LogMethodBegin(CM);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var triggersNode = rootElement.SelectSingleNode(TriggersNodeName);
|
||||||
|
parser.EnterElement(TriggersNodeName);
|
||||||
|
|
||||||
|
var triggerNodes = triggersNode.SelectNodes(TriggerNodeName);
|
||||||
|
|
||||||
|
if (triggerNodes is null || triggerNodes.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
parser.EnterElement(TriggerNodeName);
|
||||||
|
|
||||||
|
foreach (XmlElement triggerNodeElement in triggerNodes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Trigger trigger = new Trigger(triggerNodeElement, parser);
|
||||||
|
|
||||||
|
if (trigger is null || !trigger.IsValid || Triggers.ContainsKey(trigger.Event))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Triggers.Add(trigger.Event, trigger);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
parser.SelectElementNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.LeaveElement(TriggerNodeName);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
parser.LeaveElement(TriggersNodeName);
|
||||||
|
LogMethodEnd(CM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
F4SD-ActionConnector/Models/HttpCallDefinition.cs
Normal file
30
F4SD-ActionConnector/Models/HttpCallDefinition.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using C4IT.XML;
|
||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Models
|
||||||
|
{
|
||||||
|
public sealed class HttpCallDefinition : ActionDefinitionBase
|
||||||
|
{
|
||||||
|
public override ActionType Type => ActionType.HttpCall;
|
||||||
|
|
||||||
|
public string Url { get; internal set; }
|
||||||
|
public HttpMethod Method { get; internal set; } = HttpMethod.Post;
|
||||||
|
public TimeSpan Timeout { get; internal set; } = TimeSpan.FromSeconds(30);
|
||||||
|
public IDictionary<string, string> Headers { get; internal set; } = new Dictionary<string, string>();
|
||||||
|
public string Body { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// jsonPath expressions keyed by field name, used to extract values from the response.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<string, string> MappedFieldJsonPaths { get; internal set; } = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
internal HttpCallDefinition(XmlElement xNode, cXmlParser parser) : base(xNode, parser)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
F4SD-ActionConnector/Models/QuickActionDefinition.cs
Normal file
105
F4SD-ActionConnector/Models/QuickActionDefinition.cs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
using C4IT.XML;
|
||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Xml;
|
||||||
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Models
|
||||||
|
{
|
||||||
|
public sealed class QuickActionDefinition : ActionDefinitionBase
|
||||||
|
{
|
||||||
|
private const string ParametersNodeName = "Parameters";
|
||||||
|
private const string ParameterNodeName = "Parameter";
|
||||||
|
|
||||||
|
public override ActionType Type => ActionType.QuickAction;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reference to the Quick Action to invoke, e.g. "Protocol case in JIRA".
|
||||||
|
/// </summary>
|
||||||
|
public string QuickActionRef { get; internal set; }
|
||||||
|
|
||||||
|
public IDictionary<string, string> Parameters { get; private set; } = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
internal QuickActionDefinition(XmlElement xNode, cXmlParser parser) : base(xNode, parser)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!IsValid) return; else IsValid = false;
|
||||||
|
|
||||||
|
XmlNode quickActionRefNode = xNode.SelectSingleNode("QuickActionRef");
|
||||||
|
if (quickActionRefNode is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QuickActionRef = cXmlParser.GetInnerTextFromXmlElement(quickActionRefNode);
|
||||||
|
|
||||||
|
if (QuickActionRef is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XmlNode parametersNode = xNode.SelectSingleNode(ParametersNodeName);
|
||||||
|
if (parametersNode != null && parametersNode is XmlElement paramtersNodeElement)
|
||||||
|
ParseParametersElement(paramtersNodeElement, parser);
|
||||||
|
|
||||||
|
IsValid = true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseParametersElement(XmlElement parametersNodeElement, cXmlParser parser)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parser.EnterElement(ParametersNodeName);
|
||||||
|
|
||||||
|
XmlNodeList parameterNodes = parametersNodeElement.SelectNodes(ParameterNodeName);
|
||||||
|
|
||||||
|
if (parameterNodes?.Count > 0)
|
||||||
|
parser.EnterElement(ParameterNodeName);
|
||||||
|
|
||||||
|
foreach (XmlElement parameterNode in parameterNodes)
|
||||||
|
{
|
||||||
|
ParseParameterElement(parameterNode, parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameterNodes?.Count > 0)
|
||||||
|
parser.LeaveElement(ParameterNodeName);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
parser.LeaveElement(ParametersNodeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseParameterElement(XmlElement parameterNode, cXmlParser parser)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string parameterName = cXmlParser.GetStringFromXmlAttribute(parameterNode, "Name");
|
||||||
|
string parameterVariable = cXmlParser.GetInnerTextFromXmlElement(parameterNode);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(parameterName) || string.IsNullOrEmpty(parameterVariable))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Parameters.ContainsKey(parameterName))
|
||||||
|
LogEntry($"A paramter with name '{parameterName}' does allready exist.", C4IT.Logging.LogLevels.Warning);
|
||||||
|
else
|
||||||
|
Parameters.Add(parameterName, parameterVariable);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
parser.SelectElementNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
101
F4SD-ActionConnector/Models/Trigger.cs
Normal file
101
F4SD-ActionConnector/Models/Trigger.cs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
using C4IT.XML;
|
||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Models
|
||||||
|
{
|
||||||
|
public class Trigger
|
||||||
|
{
|
||||||
|
public TriggerEvent Event { get; set; }
|
||||||
|
|
||||||
|
public IDictionary<string, ActionDefinitionBase> Actions { get; } = new Dictionary<string, ActionDefinitionBase>();
|
||||||
|
|
||||||
|
public bool IsValid { get; private set; }
|
||||||
|
|
||||||
|
private const string ActionsNodeName = "Actions";
|
||||||
|
private const string ActionNodeName = "Action";
|
||||||
|
|
||||||
|
internal Trigger(XmlElement xNode, cXmlParser parser)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Event = cXmlParser.GetEnumFromAttribute(xNode, "event", TriggerEvent.Unknown);
|
||||||
|
|
||||||
|
XmlNode actionsNode = xNode.SelectSingleNode(ActionsNodeName);
|
||||||
|
|
||||||
|
if (actionsNode is null || !(actionsNode is XmlElement actionsNodeElement))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ParseActionsNode(actionsNodeElement, parser);
|
||||||
|
|
||||||
|
IsValid = true; ;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseActionsNode(XmlElement actionsNode, cXmlParser parser)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parser.EnterElement(ActionsNodeName);
|
||||||
|
|
||||||
|
var actionNodes = actionsNode.SelectNodes(ActionNodeName);
|
||||||
|
if (actionNodes is null || actionNodes.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
parser.EnterElement(ActionNodeName);
|
||||||
|
|
||||||
|
foreach (XmlElement actionNode in actionNodes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ActionType type = cXmlParser.GetEnumFromAttribute(actionNode, "Type", ActionType.Unknown);
|
||||||
|
|
||||||
|
ActionDefinitionBase actionDefinition = null;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ActionType.QuickAction:
|
||||||
|
actionDefinition = new QuickActionDefinition(actionNode, parser);
|
||||||
|
break;
|
||||||
|
case ActionType.HttpCall:
|
||||||
|
break;
|
||||||
|
case ActionType.Unknown:
|
||||||
|
case ActionType.Webhook:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionDefinition?.Id != null && !Actions.ContainsKey(actionDefinition.Id))
|
||||||
|
Actions.Add(actionDefinition.Id, actionDefinition);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
parser.SelectElementNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.LeaveElement(ActionNodeName);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
parser.LeaveElement(ActionsNodeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Payloads
|
||||||
|
{
|
||||||
|
public sealed class ApplicationStartupPayload : PayloadBase
|
||||||
|
{
|
||||||
|
public override TriggerEvent Event => TriggerEvent.ApplicationStartup;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
F4SD-ActionConnector/Payloads/CaseClosedPayload.cs
Normal file
17
F4SD-ActionConnector/Payloads/CaseClosedPayload.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Payloads
|
||||||
|
{
|
||||||
|
public sealed class CaseClosedPayload : PayloadBase
|
||||||
|
{
|
||||||
|
public override TriggerEvent Event => TriggerEvent.CaseClosed;
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Subject { get; set; }
|
||||||
|
public string Priority { get; set; }
|
||||||
|
public Guid UserId { get; set; }
|
||||||
|
public string ClosedByUserName { get; set; }
|
||||||
|
public DateTime ClosedAt { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
F4SD-ActionConnector/Payloads/CaseCreatedPayload.cs
Normal file
14
F4SD-ActionConnector/Payloads/CaseCreatedPayload.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Payloads
|
||||||
|
{
|
||||||
|
public sealed class CaseCreatedPayload : PayloadBase
|
||||||
|
{
|
||||||
|
public override TriggerEvent Event => TriggerEvent.CaseCreated;
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string UserId { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
9
F4SD-ActionConnector/Payloads/PayloadBase.cs
Normal file
9
F4SD-ActionConnector/Payloads/PayloadBase.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using F4SD.ActionConnector.Enumerations;
|
||||||
|
|
||||||
|
namespace F4SD.ActionConnector.Payloads
|
||||||
|
{
|
||||||
|
public abstract class PayloadBase
|
||||||
|
{
|
||||||
|
public abstract TriggerEvent Event { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,6 +59,7 @@ namespace F4SD_AdaptableIcon.Enums
|
|||||||
misc_tool,
|
misc_tool,
|
||||||
misc_user,
|
misc_user,
|
||||||
misc_user_disabled,
|
misc_user_disabled,
|
||||||
|
misc_disabledOverlay,
|
||||||
|
|
||||||
//StatusIcons
|
//StatusIcons
|
||||||
status_bad,
|
status_bad,
|
||||||
|
|||||||
@@ -519,6 +519,13 @@ namespace FasdDesktopUi.Basics.UserControls.AdaptableIcon
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{ enumInternIcons.misc_disabledOverlay,
|
||||||
|
new PathGeometry[]
|
||||||
|
{
|
||||||
|
PathGeometry.CreateFromGeometry(Geometry.Parse("F1 M7.8133 5.364l-.844-.62L1.1307.4627c-.5307-.4014-1.1307.4013-.5987.8026L6.1253 5.364l.844.62 5.8387 4.2813c.536.396 1.1307-.412.5933-.808 Z")),
|
||||||
|
null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
41
F4SD-Docu-Engine/DocuEngine.cs
Normal file
41
F4SD-Docu-Engine/DocuEngine.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using F4SD.DocuEngine.DocuEngineDataProvider;
|
||||||
|
using F4SD.DocuEngine.DocuEngineParser;
|
||||||
|
using F4SD.DocuEngine.DocuEngineParser.ContentBlock;
|
||||||
|
using F4SD.DocuEngine.DocuEngineParser.Exceptions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace F4SD.DocuEngine
|
||||||
|
{
|
||||||
|
public class DocuEngine
|
||||||
|
{
|
||||||
|
public string DocuTemplate { get; private set; }
|
||||||
|
public IDocuEngineDataContainer Container { get; private set; }
|
||||||
|
private ParsingContext parsingContext;
|
||||||
|
|
||||||
|
public DocuEngine(string docuTemplate, IDocuEngineDataContainer container)
|
||||||
|
{
|
||||||
|
DocuTemplate = docuTemplate;
|
||||||
|
Container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ParseTemplate()
|
||||||
|
{
|
||||||
|
var index = 0;
|
||||||
|
parsingContext = new ParsingContext();
|
||||||
|
ContentBlock contentBlock = new ContentBlock(DocuTemplate, Container);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parsingContext.Append(contentBlock.ParseContentBlock(ref index));
|
||||||
|
}
|
||||||
|
catch (DocuEngineParser.Exceptions.DocuEngineParserException parserException)
|
||||||
|
{
|
||||||
|
parsingContext.Append(parserException.CurrentText);
|
||||||
|
parsingContext.Append(parserException.PrintedErrorMessage);
|
||||||
|
return parsingContext.GetFinalText();
|
||||||
|
}
|
||||||
|
return parsingContext.GetFinalText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
using C4IT.F4SD.DisplayFormatting;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace F4SD.DocuEngine.DocuEngineDataProvider
|
||||||
|
{
|
||||||
|
public class DocuEngineDataProperty : IDocuEngineDataProperty
|
||||||
|
{
|
||||||
|
public object Value { get; set; }
|
||||||
|
public RawValueType? ValueType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DocuEngineDataContainer : Dictionary<string, IDocuEngineDataToken>, IDocuEngineDataContainer
|
||||||
|
{
|
||||||
|
public IDocuEngineDataToken GetByName(string tokenName)
|
||||||
|
{
|
||||||
|
var tokenTree = tokenName.Split('.');
|
||||||
|
if (this.TryGetValue(tokenTree[0], out IDocuEngineDataToken token))
|
||||||
|
{
|
||||||
|
if (tokenTree.Length > 1)
|
||||||
|
{
|
||||||
|
switch (token)
|
||||||
|
{
|
||||||
|
case IDocuEngineDataContainer container:
|
||||||
|
return container.GetByName(string.Join(".", tokenTree.Skip(1)));
|
||||||
|
case IDocuEngineDataProperty property:
|
||||||
|
return property;
|
||||||
|
case IDocuEngineDataEnumeration enumeration:
|
||||||
|
return new DocuEngineDataProperty() { Value = tokenTree[0] };
|
||||||
|
default:
|
||||||
|
//Syntax Error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (token)
|
||||||
|
{
|
||||||
|
case IDocuEngineDataContainer container:
|
||||||
|
return container;
|
||||||
|
case IDocuEngineDataProperty property:
|
||||||
|
return property;
|
||||||
|
case IDocuEngineDataEnumeration enumeration:
|
||||||
|
return enumeration;
|
||||||
|
default:
|
||||||
|
//Syntax Error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Syntax Error
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDocuEngineDataContainer GetContainerByName(string containerName)
|
||||||
|
{
|
||||||
|
var token = GetByName(containerName);
|
||||||
|
if (token is IDocuEngineDataContainer container)
|
||||||
|
{
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDocuEngineDataProperty GetPropertyByName(string propertyName)
|
||||||
|
{
|
||||||
|
var token = GetByName(propertyName);
|
||||||
|
if (token is IDocuEngineDataProperty property)
|
||||||
|
{
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDocuEngineDataEnumeration GetEnumerationByName(string enumName)
|
||||||
|
{
|
||||||
|
var token = GetByName(enumName);
|
||||||
|
if (token is IDocuEngineDataEnumeration enumeration)
|
||||||
|
{
|
||||||
|
return enumeration;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DocuEngineDataEnumeration : List<IDocuEngineDataToken>, IDocuEngineDataEnumeration
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using C4IT.F4SD.DisplayFormatting;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace F4SD.DocuEngine.DocuEngineDataProvider
|
||||||
|
{
|
||||||
|
public interface IDocuEngineDataToken
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IDocuEngineDataIllegal : IDocuEngineDataToken
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IDocuEngineDataProperty : IDocuEngineDataToken
|
||||||
|
{
|
||||||
|
object Value { get; set; }
|
||||||
|
RawValueType? ValueType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IDocuEngineDataContainer : IDocuEngineDataToken
|
||||||
|
{
|
||||||
|
IDocuEngineDataToken GetByName(string name);
|
||||||
|
IDocuEngineDataContainer GetContainerByName(string containerName);
|
||||||
|
IDocuEngineDataEnumeration GetEnumerationByName(string enumName);
|
||||||
|
IDocuEngineDataProperty GetPropertyByName(string propertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IDocuEngineDataEnumeration : IEnumerable<IDocuEngineDataToken>, IDocuEngineDataToken
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
227
F4SD-Docu-Engine/DocuEngineParser/ContentBlock/ContentBlock.cs
Normal file
227
F4SD-Docu-Engine/DocuEngineParser/ContentBlock/ContentBlock.cs
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
using C4IT.F4SD.DisplayFormatting;
|
||||||
|
using F4SD.DocuEngine.DocuEngineDataProvider;
|
||||||
|
using F4SD.DocuEngine.DocuEngineParser.Exceptions;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace F4SD.DocuEngine.DocuEngineParser.ContentBlock
|
||||||
|
{
|
||||||
|
internal partial class ContentBlock
|
||||||
|
{
|
||||||
|
public string DocuTemplate { get; private set; }
|
||||||
|
public IDocuEngineDataContainer Container { get; private set; }
|
||||||
|
private ParsingContext parsingContext;
|
||||||
|
public ContentBlock(string DocuTemplate, IDocuEngineDataContainer Container)
|
||||||
|
{
|
||||||
|
this.DocuTemplate = DocuTemplate;
|
||||||
|
this.Container = Container;
|
||||||
|
parsingContext = new ParsingContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ParseContentBlock(ref int index)
|
||||||
|
{
|
||||||
|
bool isContentBlockFinished = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!isContentBlockFinished)
|
||||||
|
{
|
||||||
|
ParseTextBlock(ref index, out var finished);
|
||||||
|
if (finished)
|
||||||
|
{
|
||||||
|
isContentBlockFinished = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ParseCommandBlock(ref index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (DocuEngineParserException parserException)
|
||||||
|
{
|
||||||
|
parsingContext.Append(parserException.CurrentText);
|
||||||
|
parserException.AddToCurrentText(parsingContext.GetFinalText());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
return parsingContext.GetFinalText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseTextBlock(ref int index, out bool isContextBlockFinished)
|
||||||
|
{
|
||||||
|
bool foundTrigger = false;
|
||||||
|
string[] keywords = { "@@", "[[", "]]", "{{", "}}" };
|
||||||
|
string pattern = string.Join("|", keywords.Select(Regex.Escape));
|
||||||
|
Regex regex = new Regex(pattern);
|
||||||
|
isContextBlockFinished = false;
|
||||||
|
|
||||||
|
while (!foundTrigger)
|
||||||
|
{
|
||||||
|
Match match = regex.Match(DocuTemplate, index);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
parsingContext.Append(DocuTemplate.Substring(index, match.Index - index));
|
||||||
|
index = match.Index;
|
||||||
|
switch (match.Value)
|
||||||
|
{
|
||||||
|
case "@@":
|
||||||
|
if (DocuTemplate.Substring(index, 3).Equals("@@@"))
|
||||||
|
{
|
||||||
|
parsingContext.Append("@@");
|
||||||
|
index += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foundTrigger = true;
|
||||||
|
index += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "[[":
|
||||||
|
if (DocuTemplate.Substring(index, 3).Equals("[[["))
|
||||||
|
{
|
||||||
|
parsingContext.Append("[[");
|
||||||
|
index += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index += 2;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
string variableName = ParseVariableName(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (DocuTemplate.ElementAtOrDefault(index).Equals(';'))
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
string displayTypeString = ParseDisplayType(ref index);
|
||||||
|
RawValueType? displayType = null;
|
||||||
|
if (Enum.TryParse(displayTypeString, true, out RawValueType parseDisplayType))
|
||||||
|
{
|
||||||
|
displayType = parseDisplayType;
|
||||||
|
}
|
||||||
|
parsingContext.Append(SubstituteVariable(variableName, displayType));
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (DocuTemplate.Substring(index, 2).Equals("]]") && !(DocuTemplate.Substring(index, 3).Equals("]]]")))
|
||||||
|
{
|
||||||
|
index += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("]]", DocuTemplate.Substring(index, 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (DocuTemplate.Substring(index, 2).Equals("]]"))
|
||||||
|
{
|
||||||
|
parsingContext.Append(SubstituteVariable(variableName, null));
|
||||||
|
index += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("]]\" / \";", DocuTemplate.Substring(index, 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "]]":
|
||||||
|
if (DocuTemplate.Substring(index, 3).Equals("]]]"))
|
||||||
|
{
|
||||||
|
parsingContext.Append("]]");
|
||||||
|
index += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("]]]", "]]");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "{{":
|
||||||
|
if (DocuTemplate.Substring(index, 3).Equals("{{{"))
|
||||||
|
{
|
||||||
|
parsingContext.Append("{{");
|
||||||
|
index += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("{{{", "{{");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "}}":
|
||||||
|
if (DocuTemplate.Substring(index, 3).Equals("}}}"))
|
||||||
|
{
|
||||||
|
parsingContext.Append("}}");
|
||||||
|
index += 3;
|
||||||
|
}
|
||||||
|
else if (DocuTemplate.Substring(index, 3).Equals("}};"))
|
||||||
|
{
|
||||||
|
foundTrigger = true;
|
||||||
|
isContextBlockFinished = true;
|
||||||
|
index += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foundTrigger = true;
|
||||||
|
isContextBlockFinished = true;
|
||||||
|
index += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int length = DocuTemplate.Length - index;
|
||||||
|
if (length < 0)
|
||||||
|
{
|
||||||
|
length = 0;
|
||||||
|
}
|
||||||
|
else if (length > 15)
|
||||||
|
{
|
||||||
|
length = 15;
|
||||||
|
}
|
||||||
|
throw new SyntaxErrorException("}};", DocuTemplate.Substring(index, length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseCommandBlock(ref int index)
|
||||||
|
{
|
||||||
|
string[] keywords = { "(" };
|
||||||
|
string pattern = string.Join("|", keywords.Select(Regex.Escape));
|
||||||
|
Regex regex = new Regex(pattern);
|
||||||
|
|
||||||
|
Match match = regex.Match(DocuTemplate, index);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
string commandName = "";
|
||||||
|
commandName = DocuTemplate.Substring(index, match.Index - index);
|
||||||
|
index = match.Index + 1;
|
||||||
|
|
||||||
|
switch (commandName)
|
||||||
|
{
|
||||||
|
case "if":
|
||||||
|
ParseIfCommand(ref index);
|
||||||
|
break;
|
||||||
|
case "switch":
|
||||||
|
ParseSwitchCommand(ref index);
|
||||||
|
break;
|
||||||
|
case "foreach":
|
||||||
|
ParseForeachCommand(ref index);
|
||||||
|
break;
|
||||||
|
case "include":
|
||||||
|
//TODO
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int length = DocuTemplate.Length - index;
|
||||||
|
if (length < 0)
|
||||||
|
{
|
||||||
|
length = 0;
|
||||||
|
}
|
||||||
|
else if (length > 15)
|
||||||
|
{
|
||||||
|
length = 15;
|
||||||
|
}
|
||||||
|
throw new SyntaxErrorException("if\" / \"switch\" / \"foreach", DocuTemplate.Substring(index, length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using F4SD.DocuEngine.DocuEngineDataProvider;
|
||||||
|
using F4SD.DocuEngine.DocuEngineParser.Exceptions;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace F4SD.DocuEngine.DocuEngineParser.ContentBlock
|
||||||
|
{
|
||||||
|
internal partial class ContentBlock
|
||||||
|
{
|
||||||
|
private void ParseForeachCommand(ref int index)
|
||||||
|
{
|
||||||
|
string variableName = "";
|
||||||
|
string enumName = "";
|
||||||
|
int tempIndex = 0;
|
||||||
|
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
variableName += ParseVariableName(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals(';')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException(";", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
enumName += ParseVariableName(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals(')')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException(")", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!DocuTemplate.Substring(index, 2).Equals("{{"))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("{{", DocuTemplate.Substring(index, 2));
|
||||||
|
}
|
||||||
|
index += 2;
|
||||||
|
IDocuEngineDataEnumeration enumeration = Container.GetEnumerationByName(enumName);
|
||||||
|
if (enumeration == null)
|
||||||
|
{
|
||||||
|
//Syntax Error
|
||||||
|
}
|
||||||
|
tempIndex = index;
|
||||||
|
foreach (var token in enumeration)
|
||||||
|
{
|
||||||
|
index = tempIndex;
|
||||||
|
ContentBlock foreachBlock = new ContentBlock(DocuTemplate, new DocuEngineDataContainer() { { variableName, token } });
|
||||||
|
parsingContext.Append(foreachBlock.ParseContentBlock(ref index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,291 @@
|
|||||||
|
using C4IT.F4SD.DisplayFormatting;
|
||||||
|
using F4SD.DocuEngine.DocuEngineParser.Exceptions;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace F4SD.DocuEngine.DocuEngineParser.ContentBlock
|
||||||
|
{
|
||||||
|
internal partial class ContentBlock
|
||||||
|
{
|
||||||
|
private string ParseVariableType(ref int index)
|
||||||
|
{
|
||||||
|
bool foundTypeEnd = false;
|
||||||
|
string variableType = "";
|
||||||
|
while (!foundTypeEnd)
|
||||||
|
{
|
||||||
|
char c = DocuTemplate.ElementAt(index);
|
||||||
|
if (char.IsLetter(c))
|
||||||
|
{
|
||||||
|
variableType += c;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foundTypeEnd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return variableType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ParseVariableName(ref int index)
|
||||||
|
{
|
||||||
|
bool foundVariableEnd = false;
|
||||||
|
string variableName = "";
|
||||||
|
while (!foundVariableEnd)
|
||||||
|
{
|
||||||
|
char c = DocuTemplate.ElementAt(index);
|
||||||
|
if (char.IsLetterOrDigit(c) || c == '.')
|
||||||
|
{
|
||||||
|
variableName += c;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foundVariableEnd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return variableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SkipWhiteSpace(ref int index)
|
||||||
|
{
|
||||||
|
bool foundNonWhiteSpace = false;
|
||||||
|
while (!foundNonWhiteSpace)
|
||||||
|
{
|
||||||
|
char c = DocuTemplate.ElementAt(index);
|
||||||
|
if (char.IsWhiteSpace(c))
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foundNonWhiteSpace = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ParseDisplayType(ref int index)
|
||||||
|
{
|
||||||
|
bool foundDisplayTypeEnd = false;
|
||||||
|
string displayType = "";
|
||||||
|
while (!foundDisplayTypeEnd)
|
||||||
|
{
|
||||||
|
char c = DocuTemplate.ElementAt(index);
|
||||||
|
if (char.IsLetterOrDigit(c))
|
||||||
|
{
|
||||||
|
displayType += c;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foundDisplayTypeEnd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return displayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SubstituteVariable(string variableName, RawValueType? displayType)
|
||||||
|
{
|
||||||
|
IRawValueFormatter rawValueFormatter = new RawValueFormatter();
|
||||||
|
|
||||||
|
var property = Container.GetPropertyByName(variableName);
|
||||||
|
if (property == null)
|
||||||
|
{
|
||||||
|
//Syntax Error
|
||||||
|
}
|
||||||
|
if (displayType != null)
|
||||||
|
{
|
||||||
|
return rawValueFormatter.GetDisplayValue(property.Value, (RawValueType)displayType, null);
|
||||||
|
}
|
||||||
|
else if (property.ValueType != null)
|
||||||
|
{
|
||||||
|
return rawValueFormatter.GetDisplayValue(property.Value, (RawValueType)property.ValueType, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return property.Value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private char ParseComparator(ref int index)
|
||||||
|
{
|
||||||
|
char comparator = DocuTemplate.ElementAtOrDefault(index);
|
||||||
|
if (!(comparator == '<' || comparator == '>' || comparator == '=' || comparator == '!'))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("<\" / \">\" / \"=\" / \"!", comparator.ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
return comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ParseValue(ref int index)
|
||||||
|
{
|
||||||
|
string value = "";
|
||||||
|
string pattern = @"("")(.*?)(""\s*\))";
|
||||||
|
Regex regex = new Regex(pattern);
|
||||||
|
Match match = regex.Match(DocuTemplate, index);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
value = match.Groups[2].Value;
|
||||||
|
string wholeMatch = match.Value.ToString();
|
||||||
|
index += wholeMatch.Length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("\"VariableName\")", "");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckCondition(string variableType, string variableName, char comparator, string value)
|
||||||
|
{
|
||||||
|
string stringVariable = "";
|
||||||
|
var property = Container.GetPropertyByName(variableName);
|
||||||
|
if (property == null)
|
||||||
|
{
|
||||||
|
//Syntax Error
|
||||||
|
}
|
||||||
|
stringVariable = property.Value.ToString();
|
||||||
|
switch (variableType)
|
||||||
|
{
|
||||||
|
case "string":
|
||||||
|
if (!(comparator == '=' || comparator == '!'))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("=\" / \"!", comparator.ToString());
|
||||||
|
}
|
||||||
|
return CompareStrings(stringVariable, comparator, value);
|
||||||
|
case "int":
|
||||||
|
if (!(comparator == '<' || comparator == '>' || comparator == '=' || comparator == '!'))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("<\" / \">\" / \"=\" / \"!", comparator.ToString());
|
||||||
|
}
|
||||||
|
if (!(int.TryParse(value, out var intValue)))
|
||||||
|
{
|
||||||
|
throw new VariableErrorException(value, "int");
|
||||||
|
}
|
||||||
|
stringVariable = stringVariable.Replace("\"", "");
|
||||||
|
if (!(int.TryParse(stringVariable, out var intVariable)))
|
||||||
|
{
|
||||||
|
throw new VariableErrorException(stringVariable, "int");
|
||||||
|
}
|
||||||
|
return CompareIntegers(intVariable, comparator, intValue);
|
||||||
|
case "bool":
|
||||||
|
if (!(comparator == '=' || comparator == '!'))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("=\" / \"!", comparator.ToString());
|
||||||
|
}
|
||||||
|
if (!(bool.TryParse(value, out var boolValue)))
|
||||||
|
{
|
||||||
|
throw new VariableErrorException(value, "bool");
|
||||||
|
}
|
||||||
|
if (!(bool.TryParse(stringVariable, out var boolVariable)))
|
||||||
|
{
|
||||||
|
throw new VariableErrorException(stringVariable, "bool");
|
||||||
|
}
|
||||||
|
return CompareBooleans(boolVariable, comparator, boolValue);
|
||||||
|
default:
|
||||||
|
throw new SyntaxErrorException("string\" / \"int\" / \"bool", variableType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CompareStrings(string variable, char comparator, string value)
|
||||||
|
{
|
||||||
|
switch (comparator)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
if (variable == value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case '!':
|
||||||
|
if (variable != value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CompareIntegers(int variable, char comparator, int value)
|
||||||
|
{
|
||||||
|
switch (comparator)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
if (variable == value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case '!':
|
||||||
|
if (variable != value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case '>':
|
||||||
|
if (variable > value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case '<':
|
||||||
|
if (variable < value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CompareBooleans(bool variable, char comparator, bool value)
|
||||||
|
{
|
||||||
|
switch (comparator)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
if (variable == value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case '!':
|
||||||
|
if (variable != value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
using F4SD.DocuEngine.DocuEngineParser.Exceptions;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace F4SD.DocuEngine.DocuEngineParser.ContentBlock
|
||||||
|
{
|
||||||
|
internal partial class ContentBlock
|
||||||
|
{
|
||||||
|
private void ParseIfCommand(ref int index)
|
||||||
|
{
|
||||||
|
string tempString = "";
|
||||||
|
bool foundTrueCondition = false;
|
||||||
|
bool foundAllElseIf = false;
|
||||||
|
int tempIndex = 0;
|
||||||
|
|
||||||
|
tempString = ParseIfBlock(ref index, out var isIfConditionTrue);
|
||||||
|
if (isIfConditionTrue)
|
||||||
|
{
|
||||||
|
foundTrueCondition = true;
|
||||||
|
parsingContext.Append(tempString);
|
||||||
|
}
|
||||||
|
tempString = "";
|
||||||
|
while (!foundAllElseIf)
|
||||||
|
{
|
||||||
|
tempIndex = index;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (DocuTemplate.Substring(index, 7).Equals("else-if"))
|
||||||
|
{
|
||||||
|
index += 7;
|
||||||
|
tempString += ParseElseIfBlock(ref index, out var isElseIfConditionTrue);
|
||||||
|
if (isElseIfConditionTrue && !foundTrueCondition)
|
||||||
|
{
|
||||||
|
foundTrueCondition = true;
|
||||||
|
parsingContext.Append(tempString);
|
||||||
|
}
|
||||||
|
tempString = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foundAllElseIf = true;
|
||||||
|
index = tempIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tempIndex = index;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (DocuTemplate.Substring(index, 4).Equals("else"))
|
||||||
|
{
|
||||||
|
index += 4;
|
||||||
|
tempString += ParseElseBlock(ref index);
|
||||||
|
if (!foundTrueCondition)
|
||||||
|
{
|
||||||
|
foundTrueCondition = true;
|
||||||
|
parsingContext.Append(tempString);
|
||||||
|
tempString = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = tempIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ParseIfBlock(ref int index, out bool isConditionTrue)
|
||||||
|
{
|
||||||
|
string returnString = "";
|
||||||
|
string variableType = "";
|
||||||
|
string variableName = "";
|
||||||
|
char comparator;
|
||||||
|
string value = "";
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
variableType += ParseVariableType(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals(';')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException(";", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
variableName += ParseVariableName(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals(';')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException(";", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
comparator = ParseComparator(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals(';')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException(";", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
value += ParseValue(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
isConditionTrue = CheckCondition(variableType, variableName, comparator, value);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!DocuTemplate.Substring(index, 2).Equals("{{"))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("{{", DocuTemplate.Substring(index, 2));
|
||||||
|
}
|
||||||
|
index += 2;
|
||||||
|
ContentBlock contentBlock = new ContentBlock(DocuTemplate, Container);
|
||||||
|
returnString += contentBlock.ParseContentBlock(ref index);
|
||||||
|
return returnString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ParseElseIfBlock(ref int index, out bool isConditionTrue)
|
||||||
|
{
|
||||||
|
string returnString = "";
|
||||||
|
string variableType = "";
|
||||||
|
string variableName = "";
|
||||||
|
char comparator;
|
||||||
|
string value = "";
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAt(index).Equals('(')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("(", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
variableType += ParseVariableType(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals(';')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException(";", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
variableName += ParseVariableName(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals(';')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException(";", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
comparator = ParseComparator(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals(';')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException(";", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
value += ParseValue(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
isConditionTrue = CheckCondition(variableType, variableName, comparator, value);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!DocuTemplate.Substring(index, 2).Equals("{{"))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("{{", DocuTemplate.Substring(index, 2));
|
||||||
|
}
|
||||||
|
index += 2;
|
||||||
|
ContentBlock contentBlock = new ContentBlock(DocuTemplate, Container);
|
||||||
|
returnString += contentBlock.ParseContentBlock(ref index);
|
||||||
|
return returnString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ParseElseBlock(ref int index)
|
||||||
|
{
|
||||||
|
string returnString = "";
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!DocuTemplate.Substring(index, 2).Equals("{{"))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("{{", DocuTemplate.Substring(index, 2));
|
||||||
|
}
|
||||||
|
index += 2;
|
||||||
|
ContentBlock contentBlock = new ContentBlock(DocuTemplate, Container);
|
||||||
|
returnString += contentBlock.ParseContentBlock(ref index);
|
||||||
|
return returnString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
using F4SD.DocuEngine.DocuEngineParser.Exceptions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace F4SD.DocuEngine.DocuEngineParser.ContentBlock
|
||||||
|
{
|
||||||
|
internal partial class ContentBlock
|
||||||
|
{
|
||||||
|
private void ParseSwitchCommand(ref int index)
|
||||||
|
{
|
||||||
|
string tempString = "";
|
||||||
|
bool foundTrueCase = false;
|
||||||
|
bool foundAllCases = false;
|
||||||
|
int tempIndex = 0;
|
||||||
|
(string VariableType, string VariableName) switchVariable = ParseSwitchBlock(ref index);
|
||||||
|
while (!foundAllCases)
|
||||||
|
{
|
||||||
|
tempIndex = index;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (DocuTemplate.Substring(index, 4).Equals("case"))
|
||||||
|
{
|
||||||
|
index += 4;
|
||||||
|
tempString += ParseCaseBlock(ref index, switchVariable, out var isCaseTrue);
|
||||||
|
if (isCaseTrue && !foundTrueCase)
|
||||||
|
{
|
||||||
|
foundTrueCase = true;
|
||||||
|
parsingContext.Append(tempString);
|
||||||
|
}
|
||||||
|
tempString = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foundAllCases = true;
|
||||||
|
index = tempIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tempIndex = index;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (DocuTemplate.Substring(index, 7).Equals("default"))
|
||||||
|
{
|
||||||
|
index += 7;
|
||||||
|
tempString += ParseDefaultBlock(ref index);
|
||||||
|
if (!foundTrueCase)
|
||||||
|
{
|
||||||
|
foundTrueCase = true;
|
||||||
|
parsingContext.Append(tempString);
|
||||||
|
tempString = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = tempIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private (string VariableType, string VariableName) ParseSwitchBlock(ref int index)
|
||||||
|
{
|
||||||
|
string variableName = "";
|
||||||
|
string variableType = "";
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
variableType = ParseVariableType(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals(';')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException(";", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
variableName = ParseVariableName(ref index);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals(')')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException(")", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!DocuTemplate.Substring(index, 2).Equals("{{"))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("{{", DocuTemplate.Substring(index, 2));
|
||||||
|
}
|
||||||
|
index += 2;
|
||||||
|
return (variableType, variableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ParseCaseBlock(ref int index, (string VariableType, string VariableName) switchVariable, out bool isCaseTrue)
|
||||||
|
{
|
||||||
|
string returnString = "";
|
||||||
|
isCaseTrue = false;
|
||||||
|
string value = "";
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!(DocuTemplate.ElementAtOrDefault(index).Equals('(')))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("(", DocuTemplate.ElementAtOrDefault(index).ToString());
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
value = ParseValue(ref index);
|
||||||
|
isCaseTrue = CheckCondition(switchVariable.VariableType, switchVariable.VariableName, '=', value);
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!DocuTemplate.Substring(index, 2).Equals("{{"))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("{{", DocuTemplate.Substring(index, 2));
|
||||||
|
}
|
||||||
|
index += 2;
|
||||||
|
ContentBlock contentBlock = new ContentBlock(DocuTemplate, Container);
|
||||||
|
returnString += contentBlock.ParseContentBlock(ref index);
|
||||||
|
return returnString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ParseDefaultBlock(ref int index)
|
||||||
|
{
|
||||||
|
string returnString = "";
|
||||||
|
SkipWhiteSpace(ref index);
|
||||||
|
if (!DocuTemplate.Substring(index, 2).Equals("{{"))
|
||||||
|
{
|
||||||
|
throw new SyntaxErrorException("{{", DocuTemplate.Substring(index, 2));
|
||||||
|
}
|
||||||
|
index += 2;
|
||||||
|
ContentBlock contentBlock = new ContentBlock(DocuTemplate, Container);
|
||||||
|
returnString += contentBlock.ParseContentBlock(ref index);
|
||||||
|
return returnString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace F4SD.DocuEngine.DocuEngineParser.Exceptions
|
||||||
|
{
|
||||||
|
internal abstract class DocuEngineParserException : Exception
|
||||||
|
{
|
||||||
|
public string CurrentText { get; protected set; }
|
||||||
|
public string PrintedErrorMessage { get; protected set; }
|
||||||
|
public DocuEngineParserException(string message) : base(message)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract void AddToCurrentText(string text);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
namespace F4SD.DocuEngine.DocuEngineParser.Exceptions
|
||||||
|
{
|
||||||
|
internal class SyntaxErrorException : DocuEngineParserException
|
||||||
|
{
|
||||||
|
private const string errorMessageTemplate = "<<Syntax Error | Expected Characters: \"{0}\" | Actual Characters: \"{1}\">>";
|
||||||
|
private const string defaultMessage = "You're syntax is wrong. Get good.";
|
||||||
|
|
||||||
|
public SyntaxErrorException(string currentText) : base(defaultMessage)
|
||||||
|
{
|
||||||
|
CurrentText = currentText;
|
||||||
|
}
|
||||||
|
public SyntaxErrorException(string expected, string actual) : base(defaultMessage)
|
||||||
|
{
|
||||||
|
PrintedErrorMessage = string.Format(errorMessageTemplate, expected, actual);
|
||||||
|
}
|
||||||
|
public SyntaxErrorException(string currentText, string expected, string actual) : base(defaultMessage)
|
||||||
|
{
|
||||||
|
CurrentText = currentText;
|
||||||
|
PrintedErrorMessage = string.Format(errorMessageTemplate, expected, actual);
|
||||||
|
}
|
||||||
|
public override void AddToCurrentText(string text)
|
||||||
|
{
|
||||||
|
CurrentText = text + CurrentText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
namespace F4SD.DocuEngine.DocuEngineParser.Exceptions
|
||||||
|
{
|
||||||
|
internal class VariableErrorException : DocuEngineParserException
|
||||||
|
{
|
||||||
|
private const string errorMessageTemplate = "<<Variable Error | \"{0}\" can't be converted to type \"{1}\">>";
|
||||||
|
private const string defaultMessage = "Your variable is the wrong type. Get good.";
|
||||||
|
public VariableErrorException(string currentText) : base(defaultMessage)
|
||||||
|
{
|
||||||
|
CurrentText = currentText;
|
||||||
|
}
|
||||||
|
public VariableErrorException(string expected, string actual) : base(defaultMessage)
|
||||||
|
{
|
||||||
|
PrintedErrorMessage = string.Format(errorMessageTemplate, expected, actual);
|
||||||
|
}
|
||||||
|
public VariableErrorException(string currentText, string expected, string actual) : base(defaultMessage)
|
||||||
|
{
|
||||||
|
CurrentText = currentText;
|
||||||
|
PrintedErrorMessage = string.Format(errorMessageTemplate, expected, actual);
|
||||||
|
}
|
||||||
|
public override void AddToCurrentText(string text)
|
||||||
|
{
|
||||||
|
CurrentText = text + CurrentText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
F4SD-Docu-Engine/DocuEngineParser/ParsingContext.cs
Normal file
13
F4SD-Docu-Engine/DocuEngineParser/ParsingContext.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace F4SD.DocuEngine.DocuEngineParser
|
||||||
|
{
|
||||||
|
internal class ParsingContext
|
||||||
|
{
|
||||||
|
private readonly StringBuilder _stringBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
public void Append(string text) => _stringBuilder.Append(text);
|
||||||
|
|
||||||
|
public string GetFinalText() => _stringBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
12
F4SD-Docu-Engine/F4SD-Docu-Engine.csproj
Normal file
12
F4SD-Docu-Engine/F4SD-Docu-Engine.csproj
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<RootNamespace>F4SD.DocuEngine</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="C4IT.F4SD.DisplayFormatting" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
13
F4SD-Gamification/CockpitAction.cs
Normal file
13
F4SD-Gamification/CockpitAction.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace F4SD.Gamification
|
||||||
|
{
|
||||||
|
public enum CockpitAction
|
||||||
|
{
|
||||||
|
CaseOpened,
|
||||||
|
CaseClosed,
|
||||||
|
QuickActionExecuted,
|
||||||
|
CopyTemplateClicked,
|
||||||
|
BuiltDirectConnection,
|
||||||
|
AddNotes,
|
||||||
|
StartRemoteConnection,
|
||||||
|
}
|
||||||
|
}
|
||||||
12
F4SD-Gamification/F4SD-Gamification.csproj
Normal file
12
F4SD-Gamification/F4SD-Gamification.csproj
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<RootNamespace>F4SD.Gamification</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<LangVersion>9.0</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
10
F4SD-Gamification/LevelEventArgs.cs
Normal file
10
F4SD-Gamification/LevelEventArgs.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace F4SD.Gamification
|
||||||
|
{
|
||||||
|
public class LevelEventArgs
|
||||||
|
{
|
||||||
|
public int CurrentLevel { get; set; }
|
||||||
|
public string LevelTitle { get; set; }
|
||||||
|
public int CurrentXp { get; set; }
|
||||||
|
public int XpRequiredForLevelUp { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
25
F4SD-Gamification/Services/GamificationService.cs
Normal file
25
F4SD-Gamification/Services/GamificationService.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace F4SD.Gamification.Services
|
||||||
|
{
|
||||||
|
public static class GamificationService
|
||||||
|
{
|
||||||
|
private static readonly LevelService _levelService = new();
|
||||||
|
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
PersistenceService.Initialize();
|
||||||
|
|
||||||
|
foreach (var action in PersistenceService.GetActions())
|
||||||
|
{
|
||||||
|
_levelService.InitializeAction(action.Action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TrackAction(CockpitAction action, params object[] args)
|
||||||
|
{
|
||||||
|
PersistenceService.Persist(action);
|
||||||
|
_levelService.TrackAction(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
178
F4SD-Gamification/Services/LevelService.cs
Normal file
178
F4SD-Gamification/Services/LevelService.cs
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace F4SD.Gamification.Services
|
||||||
|
{
|
||||||
|
public class LevelService
|
||||||
|
{
|
||||||
|
private static readonly List<(int MinimumTotalExperiencePoints, int Level)> _experienceToLevelMap = new()
|
||||||
|
{
|
||||||
|
(0,1),
|
||||||
|
(1128,2),
|
||||||
|
(2400,3),
|
||||||
|
(3832,4),
|
||||||
|
(5440,5),
|
||||||
|
(7240,6),
|
||||||
|
(9248,7),
|
||||||
|
(11480,8),
|
||||||
|
(13952,9),
|
||||||
|
(16680,10),
|
||||||
|
(19680,11),
|
||||||
|
(22968,12),
|
||||||
|
(26560,13),
|
||||||
|
(30472,14),
|
||||||
|
(34720,15),
|
||||||
|
(39320,16),
|
||||||
|
(44288,17),
|
||||||
|
(49640,18),
|
||||||
|
(55392,19),
|
||||||
|
(61560,20),
|
||||||
|
(68160,21),
|
||||||
|
(75208,22),
|
||||||
|
(82720,23),
|
||||||
|
(90712,24),
|
||||||
|
(99200,25),
|
||||||
|
(108200,26),
|
||||||
|
(117728,27),
|
||||||
|
(127800,28),
|
||||||
|
(138432,29),
|
||||||
|
(149640,30),
|
||||||
|
(161440,31),
|
||||||
|
(173848,32),
|
||||||
|
(186880,33),
|
||||||
|
(200552,34),
|
||||||
|
(214880,35),
|
||||||
|
(229880,36),
|
||||||
|
(245568,37),
|
||||||
|
(261960,38),
|
||||||
|
(279072,39),
|
||||||
|
(296920,40),
|
||||||
|
(315520,41),
|
||||||
|
(334888,42),
|
||||||
|
(355040,43),
|
||||||
|
(375992,44),
|
||||||
|
(397760,45),
|
||||||
|
(420360,46),
|
||||||
|
(443808,47),
|
||||||
|
(468120,48),
|
||||||
|
(493312,49),
|
||||||
|
(519400,50),
|
||||||
|
};
|
||||||
|
|
||||||
|
private int _totalExperiencePoints = 0;
|
||||||
|
private int _currentExperiencePoints;
|
||||||
|
|
||||||
|
private int _level;
|
||||||
|
|
||||||
|
internal void InitializeAction(CockpitAction action)
|
||||||
|
{
|
||||||
|
AddExperiencePoints(GetExperiencePointsFor(action), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void TrackAction(CockpitAction type, params object[] args)
|
||||||
|
{
|
||||||
|
AddExperiencePoints(GetExperiencePointsFor(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddExperiencePoints(int points, bool isInitialization = false)
|
||||||
|
{
|
||||||
|
_totalExperiencePoints += points;
|
||||||
|
UpdateLevel(isInitialization);
|
||||||
|
UpdateCurrentExperiencePoints();
|
||||||
|
|
||||||
|
if (isInitialization)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ExperiencePointsChanged?.Invoke(null, new LevelEventArgs()
|
||||||
|
{
|
||||||
|
CurrentLevel = _level,
|
||||||
|
LevelTitle = GetTitle(_level),
|
||||||
|
CurrentXp = _currentExperiencePoints,
|
||||||
|
XpRequiredForLevelUp = GetXpRequiredForNextLevel()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateCurrentExperiencePoints()
|
||||||
|
{
|
||||||
|
int xpForCurrentLevel = _experienceToLevelMap.FirstOrDefault(mapEntry => mapEntry.Level == _level).MinimumTotalExperiencePoints;
|
||||||
|
_currentExperiencePoints = _totalExperiencePoints - xpForCurrentLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateLevel(bool isInitialization)
|
||||||
|
{
|
||||||
|
int previousLevel = _level;
|
||||||
|
_level = _experienceToLevelMap.FirstOrDefault(mapEntry => _totalExperiencePoints < mapEntry.MinimumTotalExperiencePoints).Level - 1;
|
||||||
|
|
||||||
|
if (!isInitialization && previousLevel < _level)
|
||||||
|
LevelChanged?.Invoke(null, new LevelEventArgs() { CurrentLevel = _level, LevelTitle = GetTitle(_level) });
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetXpRequiredForNextLevel()
|
||||||
|
{
|
||||||
|
int totalXpForNextLevel = _experienceToLevelMap.FirstOrDefault(mapEntry => mapEntry.Level == _level + 1).MinimumTotalExperiencePoints;
|
||||||
|
int totalXpForCurrentLevel = _experienceToLevelMap.FirstOrDefault(mapEntry => mapEntry.Level == _level).MinimumTotalExperiencePoints;
|
||||||
|
return totalXpForNextLevel - totalXpForCurrentLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetExperiencePointsFor(CockpitAction action)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case CockpitAction.CaseOpened:
|
||||||
|
break;
|
||||||
|
case CockpitAction.CaseClosed:
|
||||||
|
return 10;
|
||||||
|
case CockpitAction.QuickActionExecuted:
|
||||||
|
return 20;
|
||||||
|
case CockpitAction.CopyTemplateClicked:
|
||||||
|
return 5;
|
||||||
|
case CockpitAction.BuiltDirectConnection:
|
||||||
|
break;
|
||||||
|
case CockpitAction.AddNotes:
|
||||||
|
break;
|
||||||
|
case CockpitAction.StartRemoteConnection:
|
||||||
|
return 50;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetTitle(int level)
|
||||||
|
{
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case <= 5:
|
||||||
|
return "Support Trainee";
|
||||||
|
case <= 10:
|
||||||
|
return "Response Assistant";
|
||||||
|
case <= 15:
|
||||||
|
return "Service Aider";
|
||||||
|
case <= 20:
|
||||||
|
return "Ticket Resolver";
|
||||||
|
case <= 25:
|
||||||
|
return "Customer Navigator";
|
||||||
|
case <= 30:
|
||||||
|
return "Incident Coordinator";
|
||||||
|
case <= 35:
|
||||||
|
return "IT Guy";
|
||||||
|
case <= 40:
|
||||||
|
return "Support Specialist";
|
||||||
|
case <= 45:
|
||||||
|
return "Service Mentor";
|
||||||
|
case <= 49:
|
||||||
|
return "Operations Lead";
|
||||||
|
case > 49:
|
||||||
|
return "Ticket Titan";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static event EventHandler<LevelEventArgs> ExperiencePointsChanged;
|
||||||
|
public static event EventHandler<LevelEventArgs> LevelChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
70
F4SD-Gamification/Services/PersistenceService.cs
Normal file
70
F4SD-Gamification/Services/PersistenceService.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace F4SD.Gamification.Services
|
||||||
|
{
|
||||||
|
internal static class PersistenceService
|
||||||
|
{
|
||||||
|
private static readonly string _databaseName = "F4SD-gmfc.txt";
|
||||||
|
private static readonly string _directory = $@"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\Consulting4IT GmbH\C4IT First Aid Service Desk";
|
||||||
|
|
||||||
|
private static string GetConnectionString()
|
||||||
|
{
|
||||||
|
return Path.Combine(_directory, _databaseName);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Persist(CockpitAction action)
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
|
||||||
|
using var writer = File.AppendText(GetConnectionString());
|
||||||
|
string actionLine = $"{DateTime.UtcNow},{action}";
|
||||||
|
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(actionLine));
|
||||||
|
writer.WriteLine(base64);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Initialize()
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(_directory);
|
||||||
|
|
||||||
|
if (!File.Exists(GetConnectionString()))
|
||||||
|
{
|
||||||
|
FileStream createdFile = File.Create(GetConnectionString());
|
||||||
|
File.SetAttributes(GetConnectionString(), FileAttributes.Hidden);
|
||||||
|
createdFile.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IEnumerable<(DateTime Time, CockpitAction Action)> GetActions()
|
||||||
|
{
|
||||||
|
using StreamReader reader = new(GetConnectionString());
|
||||||
|
|
||||||
|
string line;
|
||||||
|
while ((line = reader.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
string encodedLine = string.Empty;
|
||||||
|
|
||||||
|
try { encodedLine = Encoding.UTF8.GetString(Convert.FromBase64String(line)); }
|
||||||
|
catch { continue; }
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(encodedLine))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string[] splittedLine = encodedLine.Split(',');
|
||||||
|
|
||||||
|
if (splittedLine.Length < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!DateTime.TryParse(splittedLine[0], out var date))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(Enum.TryParse(splittedLine[1], out CockpitAction action)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
yield return new(date, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
<HintPath>.\Interop.CLMgr.dll</HintPath>
|
<HintPath>.\Interop.CLMgr.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net472" />
|
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
|
||||||
</packages>
|
</packages>
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
using C4IT.FASD.Base;
|
||||||
|
using FasdDesktopUi.Basics.Helper;
|
||||||
|
|
||||||
|
namespace F4SD.Cockpit.Client.Test.Basics.Helper;
|
||||||
|
|
||||||
|
public class TicketExternalLinkHelperTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void HasValidUserIdentity_NullIdentities_ReturnsFalse()
|
||||||
|
{
|
||||||
|
var relation = CreateTicketRelation();
|
||||||
|
|
||||||
|
Assert.False(TicketExternalLinkHelper.HasValidUserIdentity(relation));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasValidUserIdentity_EmptyUserId_ReturnsFalse()
|
||||||
|
{
|
||||||
|
var relation = CreateTicketRelation();
|
||||||
|
relation.Identities =
|
||||||
|
[
|
||||||
|
new cF4sdIdentityEntry { Class = enumFasdInformationClass.Ticket, Id = relation.id },
|
||||||
|
new cF4sdIdentityEntry { Class = enumFasdInformationClass.User, Id = Guid.Empty }
|
||||||
|
];
|
||||||
|
|
||||||
|
Assert.False(TicketExternalLinkHelper.HasValidUserIdentity(relation));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void HasValidUserIdentity_ValidUserId_ReturnsTrue()
|
||||||
|
{
|
||||||
|
var relation = CreateTicketRelation();
|
||||||
|
relation.Identities =
|
||||||
|
[
|
||||||
|
new cF4sdIdentityEntry { Class = enumFasdInformationClass.User, Id = Guid.NewGuid() }
|
||||||
|
];
|
||||||
|
|
||||||
|
Assert.True(TicketExternalLinkHelper.HasValidUserIdentity(relation));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetTicketLink_UsesProvidedPreviewLink()
|
||||||
|
{
|
||||||
|
var relation = CreateTicketRelation();
|
||||||
|
relation.Infos = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["DirectLinkPreview"] = "https://m42.example/wm/ticket/preview"
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = TicketExternalLinkHelper.TryGetTicketLink(relation, null, out var ticketLink);
|
||||||
|
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.Equal("https://m42.example/wm/ticket/preview", ticketLink.TrimEnd('/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetTicketLink_PreservesConfiguredTicketLink()
|
||||||
|
{
|
||||||
|
var relation = CreateTicketRelation();
|
||||||
|
relation.Infos = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["TicketLink"] = "matrix42-client://ticket/TCK00001"
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = TicketExternalLinkHelper.TryGetTicketLink(relation, null, out var ticketLink);
|
||||||
|
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.Equal("matrix42-client://ticket/TCK00001", ticketLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetTicketLink_BuildsPreviewLinkForOverviewRelation()
|
||||||
|
{
|
||||||
|
var relation = CreateTicketRelation();
|
||||||
|
relation.Infos = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["ActivityType"] = "SPSActivityTypeIncident"
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = TicketExternalLinkHelper.TryGetTicketLink(relation, "m42.example", out var ticketLink);
|
||||||
|
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.Equal(
|
||||||
|
$"https://m42.example/wm/app-ServiceDesk/notSet/preview-object/SPSActivityTypeIncident/{relation.id:D}/0/",
|
||||||
|
ticketLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetTicketLink_UsesDefaultTicketActivityType()
|
||||||
|
{
|
||||||
|
var relation = CreateTicketRelation();
|
||||||
|
|
||||||
|
var result = TicketExternalLinkHelper.TryGetTicketLink(relation, "https://m42.example/", out var ticketLink);
|
||||||
|
|
||||||
|
Assert.True(result);
|
||||||
|
Assert.Contains("/SPSActivityTypeTicket/", ticketLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetTicketLink_MissingTicketId_ReturnsFalse()
|
||||||
|
{
|
||||||
|
var relation = CreateTicketRelation();
|
||||||
|
relation.id = Guid.Empty;
|
||||||
|
|
||||||
|
var result = TicketExternalLinkHelper.TryGetTicketLink(relation, "https://m42.example", out var ticketLink);
|
||||||
|
|
||||||
|
Assert.False(result);
|
||||||
|
Assert.Null(ticketLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static cF4sdApiSearchResultRelation CreateTicketRelation()
|
||||||
|
{
|
||||||
|
return new cF4sdApiSearchResultRelation
|
||||||
|
{
|
||||||
|
Type = enumF4sdSearchResultClass.Ticket,
|
||||||
|
Name = "TCK00001",
|
||||||
|
DisplayName = "TCK00001",
|
||||||
|
id = Guid.NewGuid()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using C4IT.FASD.Base;
|
||||||
|
using C4IT.MultiLanguage;
|
||||||
|
using FasdDesktopUi.Basics;
|
||||||
|
using FasdDesktopUi.Basics.Models;
|
||||||
|
using FasdDesktopUi.Basics.Services.SupportCase.Controllers;
|
||||||
|
using FasdDesktopUi.Basics.UiActions;
|
||||||
|
|
||||||
|
namespace F4SD.Cockpit.Client.Test.Basics.Sevices.SupportCase.Controllers;
|
||||||
|
|
||||||
|
public class MenuDataFactoryTest
|
||||||
|
{
|
||||||
|
public MenuDataFactoryTest()
|
||||||
|
{
|
||||||
|
cMultiLanguageSupport.CurrentLanguage = "EN";
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Create_From_QuickActionDefinition()
|
||||||
|
{
|
||||||
|
cF4sdQuickActionRemoteComputer menuDataDefinition = new()
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Names = new() { ["EN"] = "Foo EN", ["DE"] = "Foo DE" },
|
||||||
|
Icon = { IconType = enumIconType.intern, Name = nameof(enumInternIcon.misc_computer) },
|
||||||
|
Descriptions = new() { ["EN"] = "Bar EN", ["DE"] = "Bar DE" },
|
||||||
|
AlternativeDescriptions = new() { ["EN"] = "FooBar EN", ["DE"] = "FooBar DE" },
|
||||||
|
Section = "Section 1",
|
||||||
|
Sections = ["Section 2", "Section 3"],
|
||||||
|
IsHidden = false
|
||||||
|
};
|
||||||
|
|
||||||
|
cMenuDataBase expected = new()
|
||||||
|
{
|
||||||
|
MenuText = "Foo EN",
|
||||||
|
MenuIcon = new cMenuDataBase.MenuIconInfo(new(F4SD_AdaptableIcon.Enums.enumInternIcons.misc_computer), null, false, null),
|
||||||
|
MenuSections = ["Section 1", "Section 2", "Section 3"],
|
||||||
|
UiAction = new cUiRemoteQuickAction(menuDataDefinition) { DisplayType = FasdDesktopUi.Basics.Enums.enumActionDisplayType.enabled }
|
||||||
|
};
|
||||||
|
|
||||||
|
cMenuDataBase actual = MenuDataFactory.Create(menuDataDefinition, [], []);
|
||||||
|
|
||||||
|
Assert.Equivalent(expected, actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
using C4IT.FASD.Base;
|
||||||
|
using C4IT.MultiLanguage;
|
||||||
|
using FasdDesktopUi.Basics.Services.Models;
|
||||||
|
using FasdDesktopUi.Basics.Services.SupportCase;
|
||||||
|
using FasdDesktopUi.Basics.Services.SupportCase.Processors;
|
||||||
|
using FasdDesktopUi.Basics.UiActions;
|
||||||
|
using NSubstitute;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace F4SD.Cockpit.Client.Test.Basics.Sevices.SupportCase;
|
||||||
|
|
||||||
|
public class SupportCaseProcessorTest
|
||||||
|
{
|
||||||
|
private readonly SupportCaseProcessor _supportCaseProcessor;
|
||||||
|
private readonly ISupportCase _mockSupportCase = Substitute.For<ISupportCase>();
|
||||||
|
|
||||||
|
private static readonly cMultiLanguageDictionary _stateTitle = new() { ["EN"] = "Bar", ["DE"] = "Bar (DE)" };
|
||||||
|
|
||||||
|
public SupportCaseProcessorTest()
|
||||||
|
{
|
||||||
|
_supportCaseProcessor = new SupportCaseProcessor();
|
||||||
|
_supportCaseProcessor.SetSupportCase(_mockSupportCase);
|
||||||
|
cMultiLanguageSupport.CurrentLanguage = "EN";
|
||||||
|
cF4SDCockpitXmlConfig.Instance = new() { HealthCardConfig = new() { SearchResultAge = 14 } };
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(GetCockpitValueDisplayDataTestData_StateInfo))]
|
||||||
|
[MemberData(nameof(GetCockpitValueDisplayDataTestData_StateLevel))]
|
||||||
|
[MemberData(nameof(GetCockpitValueDisplayDataTestData_StateTranslation))]
|
||||||
|
[MemberData(nameof(GetCockpitValueDisplayDataTestData_StateDateTime))]
|
||||||
|
[MemberData(nameof(GetCockpitValueDisplayDataTestData_StateVersion))]
|
||||||
|
[MemberData(nameof(GetCockpitValueDisplayDataTestData_StateDetails))]
|
||||||
|
public void Test_CockpitValueDisplayData(MockState mockState, CockpitValueDisplayData expected)
|
||||||
|
{
|
||||||
|
_mockSupportCase.GetSupportCaseHealthcardData(default, default, Arg.Any<bool>()).ReturnsForAnyArgs([mockState.RawData]);
|
||||||
|
|
||||||
|
CockpitValueDisplayData actual = _supportCaseProcessor.GetCockpitValueDisplayData(mockState.StateDefinition, default, default);
|
||||||
|
|
||||||
|
Assert.Equivalent(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<TheoryDataRow<MockState, CockpitValueDisplayData>> GetCockpitValueDisplayDataTestData_StateInfo()
|
||||||
|
{
|
||||||
|
yield return (new(new cHealthCardStateInfo() { Names = _stateTitle, IsNotTransparent = false }, "Foo"), new() { Title = "Bar", Values = ["Foo"], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateInfo() { Names = _stateTitle, IsNotTransparent = true }, "Foo"), new() { Title = "Bar", Values = ["Foo"], Levels = [enumHealthCardStateLevel.Info] });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<TheoryDataRow<MockState, CockpitValueDisplayData>> GetCockpitValueDisplayDataTestData_StateLevel()
|
||||||
|
{
|
||||||
|
yield return (new(new cHealthCardStateLevel() { Names = _stateTitle, Warning = 6, Error = 7, IsDirectionUp = true, IsNotTransparent = false }, 5), new() { Title = "Bar", Values = ["5"], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateLevel() { Names = _stateTitle, Warning = 6, Error = 7, IsDirectionUp = true, IsNotTransparent = true }, 5), new() { Title = "Bar", Values = ["5"], Levels = [enumHealthCardStateLevel.Ok] });
|
||||||
|
yield return (new(new cHealthCardStateLevel() { Names = _stateTitle, Warning = 6, Error = 7, IsDirectionUp = true, IsNotTransparent = true }, 6), new() { Title = "Bar", Values = ["6"], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
yield return (new(new cHealthCardStateLevel() { Names = _stateTitle, Warning = 6, Error = 7, IsDirectionUp = true, IsNotTransparent = true }, 7), new() { Title = "Bar", Values = ["7"], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
yield return (new(new cHealthCardStateLevel() { Names = _stateTitle, Warning = 4, Error = 2, IsDirectionUp = false, IsNotTransparent = false }, 5), new() { Title = "Bar", Values = ["5"], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateLevel() { Names = _stateTitle, Warning = 4, Error = 2, IsDirectionUp = false, IsNotTransparent = true }, 5), new() { Title = "Bar", Values = ["5"], Levels = [enumHealthCardStateLevel.Ok] });
|
||||||
|
yield return (new(new cHealthCardStateLevel() { Names = _stateTitle, Warning = 4, Error = 2, IsDirectionUp = false, IsNotTransparent = true }, 4), new() { Title = "Bar", Values = ["4"], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
yield return (new(new cHealthCardStateLevel() { Names = _stateTitle, Warning = 4, Error = 2, IsDirectionUp = false, IsNotTransparent = true }, 2), new() { Title = "Bar", Values = ["2"], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<TheoryDataRow<MockState, CockpitValueDisplayData>> GetCockpitValueDisplayDataTestData_StateTranslation()
|
||||||
|
{
|
||||||
|
cF4SDCockpitXmlConfig translationConfigNode = new() { HealthCardConfig = new cF4SDHealthCardConfig() };
|
||||||
|
translationConfigNode.Translations.Add("MyTranslation", new cHealthCardTranslator()
|
||||||
|
{
|
||||||
|
DefaultTranslation = new() { Translation = new() { ["EN"] = "Foo translated" }, StateLevel = enumHealthCardStateLevel.Error },
|
||||||
|
Translations = [
|
||||||
|
new() { Translation = new() { ["EN"] = "Foo Info translated"}, Values = ["Foo Info"], StateLevel = enumHealthCardStateLevel.Info},
|
||||||
|
new() { Translation = new() { ["EN"] = "Foo Ok translated"}, Values = ["Foo Ok"], StateLevel = enumHealthCardStateLevel.Ok},
|
||||||
|
new() { Translation = new() { ["EN"] = "Foo Warning translated"}, Values = ["Foo Warning"], StateLevel = enumHealthCardStateLevel.Warning},
|
||||||
|
new() { Translation = new() { ["EN"] = "Foo Error translated"}, Values = ["Foo Error"], StateLevel = enumHealthCardStateLevel.Error},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
yield return (new(new cHealthCardStateTranslation(translationConfigNode) { Names = _stateTitle, Translation = "MyTranslation", IsNotTransparent = false }, "Foo"), new() { Title = "Bar", Values = ["Foo translated"], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
yield return (new(new cHealthCardStateTranslation(translationConfigNode) { Names = _stateTitle, Translation = "MyTranslation", IsNotTransparent = false }, "Foo Ok"), new() { Title = "Bar", Values = ["Foo Ok translated"], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateTranslation(translationConfigNode) { Names = _stateTitle, Translation = "MyTranslation", IsNotTransparent = true }, "Foo Ok"), new() { Title = "Bar", Values = ["Foo Ok translated"], Levels = [enumHealthCardStateLevel.Ok] });
|
||||||
|
yield return (new(new cHealthCardStateTranslation(translationConfigNode) { Names = _stateTitle, Translation = "MyTranslation", IsNotTransparent = false }, "Foo Info"), new() { Title = "Bar", Values = ["Foo Info translated"], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateTranslation(translationConfigNode) { Names = _stateTitle, Translation = "MyTranslation", IsNotTransparent = true }, "Foo Info"), new() { Title = "Bar", Values = ["Foo Info translated"], Levels = [enumHealthCardStateLevel.Info] });
|
||||||
|
yield return (new(new cHealthCardStateTranslation(translationConfigNode) { Names = _stateTitle, Translation = "MyTranslation", IsNotTransparent = true }, "Foo Warning"), new() { Title = "Bar", Values = ["Foo Warning translated"], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
yield return (new(new cHealthCardStateTranslation(translationConfigNode) { Names = _stateTitle, Translation = "MyTranslation", IsNotTransparent = true }, "Foo Error"), new() { Title = "Bar", Values = ["Foo Error translated"], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
|
||||||
|
yield return (new(new cHealthCardStateTranslation(translationConfigNode) { Names = _stateTitle, Translation = "NoTranslation", IsNotTransparent = false }, "Foo Ok"), new() { Title = "Bar", Values = [null], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<TheoryDataRow<MockState, CockpitValueDisplayData>> GetCockpitValueDisplayDataTestData_StateDateTime()
|
||||||
|
{
|
||||||
|
yield return (new(new cHealthCardStateDateTime() { Names = _stateTitle, WarningHours = 6, ErrorHours = 7, IsDirectionUp = true, IsNotTransparent = false }, DateTime.UtcNow.ToString(CultureInfo.CurrentCulture)), new() { Title = "Bar", Values = [DateTime.UtcNow.ToString(CultureInfo.CurrentCulture)], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateDateTime() { Names = _stateTitle, WarningHours = 6, ErrorHours = 7, IsDirectionUp = true, IsNotTransparent = true }, DateTime.UtcNow.ToString(CultureInfo.CurrentCulture)), new() { Title = "Bar", Values = [DateTime.UtcNow.ToString(CultureInfo.CurrentCulture)], Levels = [enumHealthCardStateLevel.Ok] });
|
||||||
|
yield return (new(new cHealthCardStateDateTime() { Names = _stateTitle, WarningHours = 6, ErrorHours = 7, IsDirectionUp = true, IsNotTransparent = true }, DateTime.UtcNow.AddHours(-6).ToString(CultureInfo.CurrentCulture)), new() { Title = "Bar", Values = [DateTime.UtcNow.AddHours(-6).ToString(CultureInfo.CurrentCulture)], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
yield return (new(new cHealthCardStateDateTime() { Names = _stateTitle, WarningHours = 6, ErrorHours = 7, IsDirectionUp = true, IsNotTransparent = true }, DateTime.UtcNow.AddHours(-7).ToString(CultureInfo.CurrentCulture)), new() { Title = "Bar", Values = [DateTime.UtcNow.AddHours(-7).ToString(CultureInfo.CurrentCulture)], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
yield return (new(new cHealthCardStateDateTime() { Names = _stateTitle, WarningHours = 4, ErrorHours = 2, IsDirectionUp = false, IsNotTransparent = false }, DateTime.UtcNow.AddHours(-5).ToString(CultureInfo.CurrentCulture)), new() { Title = "Bar", Values = [DateTime.UtcNow.AddHours(-5).ToString(CultureInfo.CurrentCulture)], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateDateTime() { Names = _stateTitle, WarningHours = 4, ErrorHours = 2, IsDirectionUp = false, IsNotTransparent = true }, DateTime.UtcNow.AddHours(-5).ToString(CultureInfo.CurrentCulture)), new() { Title = "Bar", Values = [DateTime.UtcNow.AddHours(-5).ToString(CultureInfo.CurrentCulture)], Levels = [enumHealthCardStateLevel.Ok] });
|
||||||
|
yield return (new(new cHealthCardStateDateTime() { Names = _stateTitle, WarningHours = 4, ErrorHours = 2, IsDirectionUp = false, IsNotTransparent = true }, DateTime.UtcNow.AddHours(-4).ToString(CultureInfo.CurrentCulture)), new() { Title = "Bar", Values = [DateTime.UtcNow.AddHours(-4).ToString(CultureInfo.CurrentCulture)], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
yield return (new(new cHealthCardStateDateTime() { Names = _stateTitle, WarningHours = 4, ErrorHours = 2, IsDirectionUp = false, IsNotTransparent = true }, DateTime.UtcNow.AddHours(-2).ToString(CultureInfo.CurrentCulture)), new() { Title = "Bar", Values = [DateTime.UtcNow.AddHours(-2).ToString(CultureInfo.CurrentCulture)], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<TheoryDataRow<MockState, CockpitValueDisplayData>> GetCockpitValueDisplayDataTestData_StateVersion()
|
||||||
|
{
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("4.2.4.2"), Error = Version.Parse("6.7.6.7"), IsDirectionUp = true, IsNotTransparent = false }, "4.2.4.1"), new() { Title = "Bar", Values = ["4.2.4.1"], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("4.2.4.2"), Error = Version.Parse("6.7.6.7"), IsDirectionUp = true, IsNotTransparent = true }, "4.2.4.1"), new() { Title = "Bar", Values = ["4.2.4.1"], Levels = [enumHealthCardStateLevel.Ok] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("4.2.4.2"), Error = Version.Parse("6.7.6.7"), IsDirectionUp = true, IsNotTransparent = true }, "4.2.4.2"), new() { Title = "Bar", Values = ["4.2.4.2"], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("4.2.4.2"), Error = Version.Parse("6.7.6.7"), IsDirectionUp = true, IsNotTransparent = true }, "6.7.6.7"), new() { Title = "Bar", Values = ["6.7.6.7"], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("6.7.6.7"), Error = Version.Parse("4.2.4.2"), IsDirectionUp = false, IsNotTransparent = false }, "6.7.6.8"), new() { Title = "Bar", Values = ["6.7.6.8"], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("6.7.6.7"), Error = Version.Parse("4.2.4.2"), IsDirectionUp = false, IsNotTransparent = true }, "6.7.6.8"), new() { Title = "Bar", Values = ["6.7.6.8"], Levels = [enumHealthCardStateLevel.Ok] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("6.7.6.7"), Error = Version.Parse("4.2.4.2"), IsDirectionUp = false, IsNotTransparent = true }, "6.7.6.7"), new() { Title = "Bar", Values = ["6.7.6.7"], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("6.7.6.7"), Error = Version.Parse("4.2.4.2"), IsDirectionUp = false, IsNotTransparent = true }, "4.2.4.2"), new() { Title = "Bar", Values = ["4.2.4.2"], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("4.2.4.2"), Error = Version.Parse("6.7.6.7"), IsDirectionUp = true, IsNotTransparent = false }, Version.Parse("4.2.4.1")), new() { Title = "Bar", Values = ["4.2.4.1"], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("4.2.4.2"), Error = Version.Parse("6.7.6.7"), IsDirectionUp = true, IsNotTransparent = true }, Version.Parse("4.2.4.1")), new() { Title = "Bar", Values = ["4.2.4.1"], Levels = [enumHealthCardStateLevel.Ok] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("4.2.4.2"), Error = Version.Parse("6.7.6.7"), IsDirectionUp = true, IsNotTransparent = true }, Version.Parse("4.2.4.2")), new() { Title = "Bar", Values = ["4.2.4.2"], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("4.2.4.2"), Error = Version.Parse("6.7.6.7"), IsDirectionUp = true, IsNotTransparent = true }, Version.Parse("6.7.6.7")), new() { Title = "Bar", Values = ["6.7.6.7"], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("6.7.6.7"), Error = Version.Parse("4.2.4.2"), IsDirectionUp = false, IsNotTransparent = false }, Version.Parse("6.7.6.8")), new() { Title = "Bar", Values = ["6.7.6.8"], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("6.7.6.7"), Error = Version.Parse("4.2.4.2"), IsDirectionUp = false, IsNotTransparent = true }, Version.Parse("6.7.6.8")), new() { Title = "Bar", Values = ["6.7.6.8"], Levels = [enumHealthCardStateLevel.Ok] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("6.7.6.7"), Error = Version.Parse("4.2.4.2"), IsDirectionUp = false, IsNotTransparent = true }, Version.Parse("6.7.6.7")), new() { Title = "Bar", Values = ["6.7.6.7"], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
yield return (new(new cHealthCardStateVersion() { Names = _stateTitle, Warning = Version.Parse("6.7.6.7"), Error = Version.Parse("4.2.4.2"), IsDirectionUp = false, IsNotTransparent = true }, Version.Parse("4.2.4.2")), new() { Title = "Bar", Values = ["4.2.4.2"], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<TheoryDataRow<MockState, CockpitValueDisplayData>> GetCockpitValueDisplayDataTestData_StateDetails()
|
||||||
|
{
|
||||||
|
cMultiLanguageSupport.CurrentLanguage = "EN";
|
||||||
|
|
||||||
|
cHealthCardStateInfo stateDefinitionWithDetails = new() { Names = _stateTitle };
|
||||||
|
stateDefinitionWithDetails.Details = new cHealthCardDetailsValued(stateDefinitionWithDetails) { Format = cHealthCardDetailsValued.ValuedFormat.csv, RowSeparator = ',', ColSeparator = null };
|
||||||
|
yield return (new(stateDefinitionWithDetails, "42:42:42:42:42:42,67:67:67:67:67:67,69:69:69:69:69:69,,C0:FE:C0:FE:C0:FE"), new() { Title = "Bar", Values = ["4"], Levels = [enumHealthCardStateLevel.None], UiActions = [new cShowDetailedDataAction(stateDefinitionWithDetails, 0, null) { DisplayType = FasdDesktopUi.Basics.Enums.enumActionDisplayType.enabled }] });
|
||||||
|
|
||||||
|
stateDefinitionWithDetails = new() { Names = _stateTitle };
|
||||||
|
stateDefinitionWithDetails.Details = new cHealthCardDetailsValued(stateDefinitionWithDetails) { Format = cHealthCardDetailsValued.ValuedFormat.json, RowSeparator = ',', ColSeparator = null };
|
||||||
|
stateDefinitionWithDetails.Details.Add(new cHealthCardDetailsColumn() { Names = _stateTitle, Column = "Status" });
|
||||||
|
stateDefinitionWithDetails.Details.Add(new cHealthCardDetailsColumn() { Names = new() { ["EN"] = "Hello" }, Column = "Name" });
|
||||||
|
yield return (new(stateDefinitionWithDetails, "[{\"Availability\":2,\"BatteryStatus\":2,\"Caption\":\"Interner Akku\",\"Description\":\"Interner Akku\",\"EstimatedRunTime\":71582788,\"Name\":\"DELL 803W64C7\",\"Status\":\"OK\"}]"), new() { Title = "Bar", Values = ["OK"], Levels = [enumHealthCardStateLevel.None], UiActions = [new cShowDetailedDataAction(stateDefinitionWithDetails, 0, null) { DisplayType = FasdDesktopUi.Basics.Enums.enumActionDisplayType.enabled }] });
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(GetCockpitValueDisplayDataTestData_StateRefLink))]
|
||||||
|
public void Test_CockpitValueDisplayData_RefLink(MockState mockState, MockState referencedMockState, CockpitValueDisplayData expected)
|
||||||
|
{
|
||||||
|
_mockSupportCase.GetSupportCaseHealthcardData(default, Arg.Is(referencedMockState.StateDefinition.DatabaseInfo), Arg.Any<bool>()).Returns([referencedMockState.RawData]);
|
||||||
|
|
||||||
|
if (referencedMockState.StateDefinition is cHealthCardStateAggregation aggregation)
|
||||||
|
{
|
||||||
|
foreach (var state in aggregation.States)
|
||||||
|
{
|
||||||
|
_mockSupportCase.GetSupportCaseHealthcardData(default, Arg.Is(state.DatabaseInfo), Arg.Any<bool>()).Returns([42]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_mockSupportCase.GetSupportCaseHealthcardData(default, Arg.Is(mockState.StateDefinition.DatabaseInfo), Arg.Any<bool>()).Returns([mockState.RawData]);
|
||||||
|
|
||||||
|
CockpitValueDisplayData actual = _supportCaseProcessor.GetCockpitValueDisplayData(mockState.StateDefinition, default, default);
|
||||||
|
|
||||||
|
Assert.Equivalent(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<TheoryDataRow<MockState, MockState, CockpitValueDisplayData>> GetCockpitValueDisplayDataTestData_StateRefLink()
|
||||||
|
{
|
||||||
|
const int referenceValue = 42;
|
||||||
|
|
||||||
|
var levelNoneStateDefinition = new cHealthCardStateLevel() { Name = "MyReferenceNone", DatabaseInfo = new() { ValueTable = "Foo", ValueColumn = "BarNone" }, Warning = referenceValue + 1, Error = referenceValue + 2, IsDirectionUp = true, IsNotTransparent = false };
|
||||||
|
var levelInfoStateDefinition = new cHealthCardStateInfo() { Name = "MyReferenceInfo", DatabaseInfo = new() { ValueTable = "Foo", ValueColumn = "BarInfo" }, IsNotTransparent = true };
|
||||||
|
var levelOkStateDefinition = new cHealthCardStateLevel() { Name = "MyReferenceOk", DatabaseInfo = new() { ValueTable = "Foo", ValueColumn = "BarOk" }, Warning = referenceValue + 1, Error = referenceValue + 2, IsDirectionUp = true, IsNotTransparent = true };
|
||||||
|
var levelWarningStateDefinition = new cHealthCardStateLevel() { Name = "MyReferenceWarning", DatabaseInfo = new() { ValueTable = "Foo", ValueColumn = "BarWarning" }, Warning = referenceValue, Error = referenceValue + 1, IsDirectionUp = true, IsNotTransparent = true };
|
||||||
|
var levelErrorStateDefinition = new cHealthCardStateLevel() { Name = "MyReferenceError", DatabaseInfo = new() { ValueTable = "Foo", ValueColumn = "BarError" }, Warning = referenceValue, Error = referenceValue, IsDirectionUp = true, IsNotTransparent = true };
|
||||||
|
var levelWarningAggregationDefinition = new cHealthCardStateAggregation() { Name = "MyReferenceAggregation", States = [levelOkStateDefinition, levelWarningStateDefinition] };
|
||||||
|
|
||||||
|
var stateConfigNode = new cF4SDHealthCardConfig();
|
||||||
|
stateConfigNode.Prerequisites.ReferencableStates.Add(levelNoneStateDefinition.Name, levelNoneStateDefinition);
|
||||||
|
stateConfigNode.Prerequisites.ReferencableStates.Add(levelInfoStateDefinition.Name, levelInfoStateDefinition);
|
||||||
|
stateConfigNode.Prerequisites.ReferencableStates.Add(levelOkStateDefinition.Name, levelOkStateDefinition);
|
||||||
|
stateConfigNode.Prerequisites.ReferencableStates.Add(levelWarningStateDefinition.Name, levelWarningStateDefinition);
|
||||||
|
stateConfigNode.Prerequisites.ReferencableStates.Add(levelErrorStateDefinition.Name, levelErrorStateDefinition);
|
||||||
|
stateConfigNode.Prerequisites.ReferencableStates.Add(levelWarningAggregationDefinition.Name, levelWarningAggregationDefinition);
|
||||||
|
|
||||||
|
yield return (new(new cHealthCardStateRefLink(stateConfigNode) { Names = _stateTitle, DatabaseInfo = new() { ValueTable = "Bar", ValueColumn = "Foo" }, Reference = levelNoneStateDefinition.Name }, "Foo"), new(levelNoneStateDefinition, referenceValue), new() { Title = "Bar", Values = ["Foo"], Levels = [enumHealthCardStateLevel.None] });
|
||||||
|
yield return (new(new cHealthCardStateRefLink(stateConfigNode) { Names = _stateTitle, DatabaseInfo = new() { ValueTable = "Bar", ValueColumn = "Foo" }, Reference = levelInfoStateDefinition.Name }, "Foo"), new(levelInfoStateDefinition, referenceValue), new() { Title = "Bar", Values = ["Foo"], Levels = [enumHealthCardStateLevel.Info] });
|
||||||
|
yield return (new(new cHealthCardStateRefLink(stateConfigNode) { Names = _stateTitle, DatabaseInfo = new() { ValueTable = "Bar", ValueColumn = "Foo" }, Reference = levelOkStateDefinition.Name, IsNotTransparent = true }, "Foo"), new(levelOkStateDefinition, referenceValue), new() { Title = "Bar", Values = ["Foo"], Levels = [enumHealthCardStateLevel.Ok] });
|
||||||
|
yield return (new(new cHealthCardStateRefLink(stateConfigNode) { Names = _stateTitle, DatabaseInfo = new() { ValueTable = "Bar", ValueColumn = "Foo" }, Reference = levelWarningStateDefinition.Name }, "Foo"), new(levelWarningStateDefinition, referenceValue), new() { Title = "Bar", Values = ["Foo"], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
yield return (new(new cHealthCardStateRefLink(stateConfigNode) { Names = _stateTitle, DatabaseInfo = new() { ValueTable = "Bar", ValueColumn = "Foo" }, Reference = levelErrorStateDefinition.Name }, "Foo"), new(levelErrorStateDefinition, referenceValue), new() { Title = "Bar", Values = ["Foo"], Levels = [enumHealthCardStateLevel.Error] });
|
||||||
|
yield return (new(new cHealthCardStateRefLink(stateConfigNode) { Names = _stateTitle, DatabaseInfo = new() { ValueTable = "Bar", ValueColumn = "Foo" }, Reference = levelWarningAggregationDefinition.Name }, "Foo"), new(levelWarningAggregationDefinition, referenceValue), new() { Title = "Bar", Values = ["Foo"], Levels = [enumHealthCardStateLevel.Warning] });
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(GetCockpitValueDisplayDataTestData_StateAggregation))]
|
||||||
|
public void Test_CockpitValueDisplayData_Aggregation(MockState mockState, CockpitValueDisplayData expected, params MockState[] aggregatedStates)
|
||||||
|
{
|
||||||
|
foreach (var aggregatedState in aggregatedStates)
|
||||||
|
{
|
||||||
|
_mockSupportCase.GetSupportCaseHealthcardData(default, Arg.Is(aggregatedState.StateDefinition.DatabaseInfo), Arg.Any<bool>()).Returns([aggregatedState.RawData]);
|
||||||
|
|
||||||
|
if (mockState.StateDefinition is cHealthCardStateAggregation stateAggreagtion)
|
||||||
|
stateAggreagtion.States.Add(aggregatedState.StateDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
_mockSupportCase.GetSupportCaseHealthcardData(default, Arg.Is(mockState.StateDefinition.DatabaseInfo), Arg.Any<bool>()).Returns([mockState.RawData]);
|
||||||
|
|
||||||
|
CockpitValueDisplayData actual = _supportCaseProcessor.GetCockpitValueDisplayData(mockState.StateDefinition, default, default);
|
||||||
|
|
||||||
|
Assert.Equivalent(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<TheoryDataRow<MockState, CockpitValueDisplayData, MockState[]>> GetCockpitValueDisplayDataTestData_StateAggregation()
|
||||||
|
{
|
||||||
|
MockState stateOk = new(new cHealthCardStateLevel() { DatabaseInfo = new() { ValueTable = "MyAggregated", ValueColumn = "Ok" }, Warning = 43, Error = 44, IsDirectionUp = true }, 42);
|
||||||
|
MockState stateWarning = new(new cHealthCardStateLevel() { DatabaseInfo = new() { ValueTable = "MyAggregated", ValueColumn = "Warning" }, Warning = 42, Error = 43, IsDirectionUp = true }, 42);
|
||||||
|
MockState stateError = new(new cHealthCardStateLevel() { DatabaseInfo = new() { ValueTable = "MyAggregated", ValueColumn = "Error" }, Warning = 41, Error = 42, IsDirectionUp = true }, 42);
|
||||||
|
|
||||||
|
yield return (new(new cHealthCardStateAggregation() { Names = _stateTitle, IsNotTransparent = false }, null), new() { Title = "Bar", Values = ["Ø"], Levels = [enumHealthCardStateLevel.None] }, [stateOk]);
|
||||||
|
yield return (new(new cHealthCardStateAggregation() { Names = _stateTitle, IsNotTransparent = true }, null), new() { Title = "Bar", Values = ["Ø"], Levels = [enumHealthCardStateLevel.Ok] }, [stateOk]);
|
||||||
|
yield return (new(new cHealthCardStateAggregation() { Names = _stateTitle, IsNotTransparent = true }, null), new() { Title = "Bar", Values = ["Ø"], Levels = [enumHealthCardStateLevel.Warning] }, [stateOk, stateWarning]);
|
||||||
|
yield return (new(new cHealthCardStateAggregation() { Names = _stateTitle, IsNotTransparent = true }, null), new() { Title = "Bar", Values = ["Ø"], Levels = [enumHealthCardStateLevel.Error] }, [stateOk, stateWarning, stateError]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record MockState
|
||||||
|
{
|
||||||
|
public cHealthCardStateBase StateDefinition { get; set; }
|
||||||
|
public object? RawData { get; set; }
|
||||||
|
|
||||||
|
public MockState(cHealthCardStateBase stateDefinition, object? rawData)
|
||||||
|
{
|
||||||
|
StateDefinition = stateDefinition;
|
||||||
|
RawData = rawData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -126,7 +126,7 @@ public class SupportCaseTest
|
|||||||
_supportCase.UpdateSupportCaseDataCache(relation, [dataTable]);
|
_supportCase.UpdateSupportCaseDataCache(relation, [dataTable]);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var actual = _supportCase.GetSupportCaseHealthcardData(relation, new cValueAddress() { ValueTable = tableName, ValueColumn = columnName });
|
var actual = _supportCase.GetSupportCaseHealthcardData(relation, new cValueAddress() { ValueTable = tableName, ValueColumn = columnName }, default);
|
||||||
|
|
||||||
Assert.Equal(expected, actual);
|
Assert.Equal(expected, actual);
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ public class SupportCaseTest
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
// Act
|
// Act
|
||||||
var actual = _supportCase.GetSupportCaseHealthcardData(relation, new cValueAddress() { ValueTable = "NonExistentTable", ValueColumn = "NonExistentColumn" });
|
var actual = _supportCase.GetSupportCaseHealthcardData(relation, new cValueAddress() { ValueTable = "NonExistentTable", ValueColumn = "NonExistentColumn" }, default);
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Null(actual);
|
Assert.Null(actual);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using C4IT.FASD.Cockpit.Communication;
|
||||||
using FasdDesktopUi.Basics.Services;
|
using FasdDesktopUi.Basics.Services;
|
||||||
using FasdDesktopUi.Basics.Services.Models;
|
using FasdDesktopUi.Basics.Services.Models;
|
||||||
|
|
||||||
@@ -110,6 +111,52 @@ public class TicketOverviewUpdateServiceTest
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task FetchAsync_TicketAndServiceRequestsCapability_UsesEnabledDefaultAndIsSeparatedFromCounts()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var communication = new FakeCommunication();
|
||||||
|
communication.SetCounts(TileScope.Personal, new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["ServiceRequestsNew"] = 2
|
||||||
|
});
|
||||||
|
communication.SetCounts(TileScope.Role, new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["ServiceRequestsNew"] = 4
|
||||||
|
});
|
||||||
|
|
||||||
|
var service = CreateService(communication, out _);
|
||||||
|
var availabilityChanges = 0;
|
||||||
|
service.TicketAndServiceRequestsAvailabilityChanged += (_, _) => availabilityChanges++;
|
||||||
|
Assert.True(service.TicketAndServiceRequestsEnabled);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
service.UpdateAvailability(true);
|
||||||
|
await WaitUntilAsync(() => service.AreAllScopesInitialized);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(service.TicketAndServiceRequestsEnabled);
|
||||||
|
Assert.Equal(0, availabilityChanges);
|
||||||
|
Assert.Equal(2, service.CurrentCounts["ServiceRequestsNew"].Personal);
|
||||||
|
Assert.Equal(4, service.CurrentCounts["ServiceRequestsNew"].Role);
|
||||||
|
Assert.DoesNotContain("TicketAndServiceRequestsEnabled", service.CurrentCounts.Keys);
|
||||||
|
|
||||||
|
communication.SetCounts(TileScope.Personal, new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["ServiceRequestsNew"] = 3
|
||||||
|
});
|
||||||
|
await service.FetchAsync(TileScope.Personal);
|
||||||
|
|
||||||
|
Assert.True(service.TicketAndServiceRequestsEnabled);
|
||||||
|
Assert.Equal(0, availabilityChanges);
|
||||||
|
|
||||||
|
communication.SetCapability(TileScope.Personal, false);
|
||||||
|
await service.FetchAsync(TileScope.Personal);
|
||||||
|
|
||||||
|
Assert.False(service.TicketAndServiceRequestsEnabled);
|
||||||
|
Assert.Equal(1, availabilityChanges);
|
||||||
|
}
|
||||||
|
|
||||||
private static TicketOverviewUpdateService CreateService(FakeCommunication communication, out FakeDispatcher dispatcher)
|
private static TicketOverviewUpdateService CreateService(FakeCommunication communication, out FakeDispatcher dispatcher)
|
||||||
{
|
{
|
||||||
dispatcher = new FakeDispatcher();
|
dispatcher = new FakeDispatcher();
|
||||||
@@ -149,18 +196,27 @@ public class TicketOverviewUpdateServiceTest
|
|||||||
|
|
||||||
private sealed class FakeCommunication : ITicketOverviewCommunication
|
private sealed class FakeCommunication : ITicketOverviewCommunication
|
||||||
{
|
{
|
||||||
private Dictionary<string, int> _personalCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
private cF4sdTicketOverviewCountsResult _personalResult = new cF4sdTicketOverviewCountsResult();
|
||||||
private Dictionary<string, int> _roleCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
private cF4sdTicketOverviewCountsResult _roleResult = new cF4sdTicketOverviewCountsResult();
|
||||||
|
|
||||||
public bool IsDemo()
|
public bool IsDemo()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Dictionary<string, int>> GetTicketOverviewCounts(string[] overviewKeys, bool useRoleScope)
|
public Task<cF4sdTicketOverviewCountsResult> GetTicketOverviewCounts(string[] overviewKeys, bool useRoleScope)
|
||||||
{
|
{
|
||||||
var source = useRoleScope ? _roleCounts : _personalCounts;
|
var source = useRoleScope ? _roleResult : _personalResult;
|
||||||
return Task.FromResult(new Dictionary<string, int>(source, StringComparer.OrdinalIgnoreCase));
|
return Task.FromResult(new cF4sdTicketOverviewCountsResult
|
||||||
|
{
|
||||||
|
Counts = new Dictionary<string, int>(source.Counts, StringComparer.OrdinalIgnoreCase),
|
||||||
|
Capabilities = source.Capabilities == null
|
||||||
|
? null
|
||||||
|
: new cF4sdTicketOverviewCapabilities
|
||||||
|
{
|
||||||
|
TicketAndServiceRequestsEnabled = source.Capabilities.TicketAndServiceRequestsEnabled
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterGeneratedTicket(FasdCockpitCommunicationDemo.DemoTicketRecord record)
|
public void RegisterGeneratedTicket(FasdCockpitCommunicationDemo.DemoTicketRecord record)
|
||||||
@@ -175,13 +231,22 @@ public class TicketOverviewUpdateServiceTest
|
|||||||
|
|
||||||
if (scope == TileScope.Role)
|
if (scope == TileScope.Role)
|
||||||
{
|
{
|
||||||
_roleCounts = copy;
|
_roleResult.Counts = copy;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_personalCounts = copy;
|
_personalResult.Counts = copy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetCapability(TileScope scope, bool enabled)
|
||||||
|
{
|
||||||
|
var result = scope == TileScope.Role ? _roleResult : _personalResult;
|
||||||
|
result.Capabilities = new cF4sdTicketOverviewCapabilities
|
||||||
|
{
|
||||||
|
TicketAndServiceRequestsEnabled = enabled
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class FakeDispatcher : ITicketOverviewDispatcher
|
private sealed class FakeDispatcher : ITicketOverviewDispatcher
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>F4SD.Cockpit.Client.Test</RootNamespace>
|
<RootNamespace>F4SD.Cockpit.Client.Test</RootNamespace>
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
<TargetFramework>net10.0-windows</TargetFramework>
|
||||||
|
<UseWPF>true</UseWPF>
|
||||||
<!--
|
<!--
|
||||||
To enable the Microsoft Testing Platform 'dotnet test' experience, add property:
|
To enable the Microsoft Testing Platform 'dotnet test' experience, add property:
|
||||||
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
|
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
|
||||||
@@ -27,8 +28,11 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
<PackageReference Include="MaterialIcons" Version="1.0.3" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="System.Drawing.Common" Version="10.0.3" />
|
||||||
<PackageReference Include="xunit.v3" Version="3.2.2" />
|
<PackageReference Include="xunit.v3" Version="3.2.2" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
|||||||
@@ -56,31 +56,31 @@
|
|||||||
<Reference Include="C4IT.F4SD.DisplayFormatting, Version=1.0.9509.21303, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="C4IT.F4SD.DisplayFormatting, Version=1.0.9509.21303, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\C4IT.F4SD.DisplayFormatting.1.0.0\lib\netstandard2.0\C4IT.F4SD.DisplayFormatting.dll</HintPath>
|
<HintPath>..\packages\C4IT.F4SD.DisplayFormatting.1.0.0\lib\netstandard2.0\C4IT.F4SD.DisplayFormatting.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="C4IT.F4SD.SupportCaseProtocoll, Version=1.0.9516.21165, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="C4IT.F4SD.SupportCaseProtocoll, Version=1.0.9558.28081, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\C4IT.F4SD.SupportCaseProtocoll.1.0.0\lib\netstandard2.0\C4IT.F4SD.SupportCaseProtocoll.dll</HintPath>
|
<HintPath>..\packages\C4IT.F4SD.SupportCaseProtocoll.1.0.1\lib\netstandard2.0\C4IT.F4SD.SupportCaseProtocoll.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="MaterialIcons, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="MaterialIcons, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\MaterialIcons.1.0.3\lib\MaterialIcons.dll</HintPath>
|
<HintPath>..\packages\MaterialIcons.1.0.3\lib\MaterialIcons.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=10.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=10.0.0.3, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.10.0.2\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.10.0.3\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=10.0.0.2, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=10.0.0.3, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.10.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.10.0.3\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=10.0.0.2, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=10.0.0.3, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.10.0.2\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.10.0.3\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
|
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Diagnostics.DiagnosticSource, Version=10.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Diagnostics.DiagnosticSource, Version=10.0.0.3, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.10.0.2\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
|
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.10.0.3\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
@@ -104,6 +104,9 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="..\..\C4IT FASD\_Common\C4IT.F4SD.Base.Ticket.cs">
|
||||||
|
<Link>Common\C4IT.F4SD.Base.Ticket.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\..\C4IT FASD\_Common\C4IT.F4SD.GlobalConfig.cs">
|
<Compile Include="..\..\C4IT FASD\_Common\C4IT.F4SD.GlobalConfig.cs">
|
||||||
<Link>Common\C4IT.F4SD.GlobalConfig.cs</Link>
|
<Link>Common\C4IT.F4SD.GlobalConfig.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -158,10 +161,16 @@
|
|||||||
<Compile Include="..\Shared\SharedAssemblyInfo.cs">
|
<Compile Include="..\Shared\SharedAssemblyInfo.cs">
|
||||||
<Link>Properties\SharedAssemblyInfo.cs</Link>
|
<Link>Properties\SharedAssemblyInfo.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Models\RemoteDesktopConnection\IRemoteDesktopClientInfo.cs" />
|
||||||
|
<Compile Include="Models\RemoteDesktopConnection\RemoteDesktopConnectionStatusResult.cs" />
|
||||||
|
<Compile Include="Models\TicketOverview\TicketOverviewCountsResult.cs" />
|
||||||
|
<Compile Include="RemoteDesktopCommunicationBase.cs" />
|
||||||
<Compile Include="ExternalToolExecutor.cs" />
|
<Compile Include="ExternalToolExecutor.cs" />
|
||||||
<Compile Include="F4sdCockpitCommunicationM42Base.cs" />
|
<Compile Include="F4sdCockpitCommunicationM42Base.cs" />
|
||||||
<Compile Include="FasdCockpitCommunicationBase.cs" />
|
<Compile Include="FasdCockpitCommunicationBase.cs" />
|
||||||
<Compile Include="Models\F4sdAgentScript.cs" />
|
<Compile Include="Models\F4sdAgentScript.cs" />
|
||||||
|
<Compile Include="Models\RemoteDesktopConnection\IRemoteDesktopConnectionDetails.cs" />
|
||||||
|
<Compile Include="Models\RemoteDesktopConnection\RemoteDesktopConnectionStatus.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using C4IT.FASD.Base;
|
using C4IT.FASD.Base;
|
||||||
|
using FasdCockpitBase;
|
||||||
using FasdCockpitBase.Models;
|
using FasdCockpitBase.Models;
|
||||||
|
|
||||||
namespace C4IT.FASD.Cockpit.Communication
|
namespace C4IT.FASD.Cockpit.Communication
|
||||||
@@ -23,6 +24,8 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
public cF4sdCockpitCommunicationM42Base M42 = new cF4sdCockpitCommunicationM42Base();
|
public cF4sdCockpitCommunicationM42Base M42 = new cF4sdCockpitCommunicationM42Base();
|
||||||
|
|
||||||
|
public RemoteDesktopCommunicationBase RemoteDesktopManager = new RemoteDesktopCommunicationBase();
|
||||||
|
|
||||||
public abstract bool IsDemo();
|
public abstract bool IsDemo();
|
||||||
|
|
||||||
public abstract bool CheckConnectionInfo();
|
public abstract bool CheckConnectionInfo();
|
||||||
@@ -63,13 +66,14 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
public abstract Task<cF4sdStagedSearchResultRelationTaskId> StartGatheringRelations(IEnumerable<cFasdApiSearchResultEntry> relatedTo, CancellationToken token);
|
public abstract Task<cF4sdStagedSearchResultRelationTaskId> StartGatheringRelations(IEnumerable<cFasdApiSearchResultEntry> relatedTo, CancellationToken token);
|
||||||
public abstract Task<cF4sdStagedSearchResultRelations> GetStagedRelations(Guid id, CancellationToken token);
|
public abstract Task<cF4sdStagedSearchResultRelations> GetStagedRelations(Guid id, CancellationToken token);
|
||||||
|
public abstract Task StopGatheringRelations(Guid id, CancellationToken token);
|
||||||
|
|
||||||
public abstract Task<List<cF4sdApiSearchResultRelation>> GetSearchResultRelations(enumF4sdSearchResultClass resultType, List<cFasdApiSearchResultEntry> searchResults);
|
public abstract Task<List<cF4sdApiSearchResultRelation>> GetSearchResultRelations(enumF4sdSearchResultClass resultType, List<cFasdApiSearchResultEntry> searchResults);
|
||||||
|
|
||||||
#region Ticketübersicht
|
#region Ticketübersicht
|
||||||
|
|
||||||
public abstract Task<List<cF4sdApiSearchResultRelation>> GetTicketOverviewRelations(string key, bool useRoleScope, int count);
|
public abstract Task<List<cF4sdApiSearchResultRelation>> GetTicketOverviewRelations(string key, bool useRoleScope, int count);
|
||||||
public abstract Task<Dictionary<string, int>> GetTicketOverviewCounts(IEnumerable<string> keys, bool useRoleScope);
|
public abstract Task<cF4sdTicketOverviewCountsResult> GetTicketOverviewCounts(IEnumerable<string> keys, bool useRoleScope);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -86,6 +90,29 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
public abstract Task<bool> UpdateHealthcardTableData(cF4SDWriteParameters dataParameter);
|
public abstract Task<bool> UpdateHealthcardTableData(cF4SDWriteParameters dataParameter);
|
||||||
public abstract Task<bool> Matrix42TicketFinalization(cApiM42Ticket ticketData);
|
public abstract Task<bool> Matrix42TicketFinalization(cApiM42Ticket ticketData);
|
||||||
|
|
||||||
|
public virtual async Task<cTicketFinalizationResult> FinalizeTicketAsync(cApiM42Ticket ticketData)
|
||||||
|
{
|
||||||
|
var success = await Matrix42TicketFinalization(ticketData);
|
||||||
|
var ticketId = ticketData?.Ticket;
|
||||||
|
if (ticketId == Guid.Empty)
|
||||||
|
ticketId = null;
|
||||||
|
|
||||||
|
return new cTicketFinalizationResult
|
||||||
|
{
|
||||||
|
Success = success,
|
||||||
|
TicketId = ticketId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Task<cTicketExternalLinkResult> GetTicketExternalLinkAsync(Guid ticketId, enumTicketExternalOpenMode mode)
|
||||||
|
{
|
||||||
|
return Task.FromResult(new cTicketExternalLinkResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Mode = enumTicketExternalOpenMode.None
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Task<List<List<object>>> GetQuickActionHistory(string QuickActionName, int OrgId, int DeviceId, int? UserId);
|
public abstract Task<List<List<object>>> GetQuickActionHistory(string QuickActionName, int OrgId, int DeviceId, int? UserId);
|
||||||
|
|
||||||
public abstract Task<bool> GetAgentApiAccessInfo();
|
public abstract Task<bool> GetAgentApiAccessInfo();
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace FasdCockpitBase.Models.RemoteDesktopConnection
|
||||||
|
{
|
||||||
|
public interface IRemoteDesktopClientInfo
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace FasdCockpitBase.Models.RemoteDesktopConnection
|
||||||
|
{
|
||||||
|
public interface IRemoteDesktopConnectionDetails
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace FasdCockpitBase.Models.RemoteDesktopConnection
|
||||||
|
{
|
||||||
|
public enum RemoteDesktopConnectionStatus
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Initiated,
|
||||||
|
Accepted,
|
||||||
|
Connected,
|
||||||
|
Canceled,
|
||||||
|
Finished,
|
||||||
|
Error
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace FasdCockpitBase.Models.RemoteDesktopConnection
|
||||||
|
{
|
||||||
|
public class RemoteDesktopConnectionStatusResult
|
||||||
|
{
|
||||||
|
public RemoteDesktopConnectionStatus Status { get; private set; }
|
||||||
|
|
||||||
|
public IList<string> Errors { get; set; } = new List<string>();
|
||||||
|
|
||||||
|
public RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus status)
|
||||||
|
{
|
||||||
|
Status = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace C4IT.FASD.Cockpit.Communication
|
||||||
|
{
|
||||||
|
public sealed class cF4sdTicketOverviewCountsResult
|
||||||
|
{
|
||||||
|
public Dictionary<string, int> Counts { get; set; } = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
public cF4sdTicketOverviewCapabilities Capabilities { get; set; } = new cF4sdTicketOverviewCapabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class cF4sdTicketOverviewCapabilities
|
||||||
|
{
|
||||||
|
public bool TicketAndServiceRequestsEnabled { get; set; } = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
FasdCockpitBase/RemoteDesktopCommunicationBase.cs
Normal file
29
FasdCockpitBase/RemoteDesktopCommunicationBase.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using C4IT.FASD.Base;
|
||||||
|
using FasdCockpitBase.Models.RemoteDesktopConnection;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace FasdCockpitBase
|
||||||
|
{
|
||||||
|
public class RemoteDesktopCommunicationBase
|
||||||
|
{
|
||||||
|
public virtual Task<T> InitiateConnection<T>(IRemoteDesktopClientInfo clientInfo, bool isElevated, CancellationToken token) where T : IRemoteDesktopConnectionDetails
|
||||||
|
=> Task.FromResult(default(T));
|
||||||
|
|
||||||
|
public virtual Task<RemoteDesktopConnectionStatusResult> GetConnectionStatus(Guid connectionId, CancellationToken token)
|
||||||
|
=> Task.FromResult(new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Unknown));
|
||||||
|
|
||||||
|
public virtual Task StopConnection(Guid connectionId, CancellationToken token)
|
||||||
|
=> Task.CompletedTask;
|
||||||
|
|
||||||
|
public virtual Task<HealthInformation> GetHealth(CancellationToken token)
|
||||||
|
=> Task.FromResult(new HealthInformation(HealthStatus.healthy));
|
||||||
|
|
||||||
|
public virtual Task<bool> IsRemoteDesktopCommunicationAvailable()
|
||||||
|
{
|
||||||
|
bool isRemoteViewerInstalled = true;
|
||||||
|
return Task.FromResult(isRemoteViewerInstalled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.2" newVersion="10.0.0.2" />
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.3" newVersion="10.0.0.3" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="C4IT.F4SD.DisplayFormatting" version="1.0.0" targetFramework="net472" />
|
<package id="C4IT.F4SD.DisplayFormatting" version="1.0.0" targetFramework="net472" />
|
||||||
<package id="C4IT.F4SD.SupportCaseProtocoll" version="1.0.0" targetFramework="net472" />
|
<package id="C4IT.F4SD.SupportCaseProtocoll" version="1.0.1" targetFramework="net472" />
|
||||||
<package id="MaterialIcons" version="1.0.3" targetFramework="net472" />
|
<package id="MaterialIcons" version="1.0.3" targetFramework="net472" />
|
||||||
<package id="Microsoft.Bcl.AsyncInterfaces" version="10.0.2" targetFramework="net472" />
|
<package id="Microsoft.Bcl.AsyncInterfaces" version="10.0.3" targetFramework="net472" />
|
||||||
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="10.0.2" targetFramework="net472" />
|
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="10.0.3" targetFramework="net472" />
|
||||||
<package id="Microsoft.Extensions.Logging.Abstractions" version="10.0.2" targetFramework="net472" />
|
<package id="Microsoft.Extensions.Logging.Abstractions" version="10.0.3" targetFramework="net472" />
|
||||||
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net472" />
|
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
|
||||||
<package id="System.Buffers" version="4.6.1" targetFramework="net472" />
|
<package id="System.Buffers" version="4.6.1" targetFramework="net472" />
|
||||||
<package id="System.Diagnostics.DiagnosticSource" version="10.0.2" targetFramework="net472" />
|
<package id="System.Diagnostics.DiagnosticSource" version="10.0.3" targetFramework="net472" />
|
||||||
<package id="System.Memory" version="4.6.3" targetFramework="net472" />
|
<package id="System.Memory" version="4.6.3" targetFramework="net472" />
|
||||||
<package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net472" />
|
<package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net472" />
|
||||||
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net472" />
|
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net472" />
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
@@ -95,9 +95,12 @@
|
|||||||
<Compile Include="..\Shared\SharedAssemblyInfo.cs">
|
<Compile Include="..\Shared\SharedAssemblyInfo.cs">
|
||||||
<Link>Properties\SharedAssemblyInfo.cs</Link>
|
<Link>Properties\SharedAssemblyInfo.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="RemoteDesktopCommunication\AgentRemoteDesktopCommunication.cs" />
|
||||||
<Compile Include="F4sdCockpitCommunicationM42Web.cs" />
|
<Compile Include="F4sdCockpitCommunicationM42Web.cs" />
|
||||||
<Compile Include="FasdCockpitCommunicationWeb.cs" />
|
<Compile Include="FasdCockpitCommunicationWeb.cs" />
|
||||||
<Compile Include="FasdCockpitMachineConfiguration.cs" />
|
<Compile Include="FasdCockpitMachineConfiguration.cs" />
|
||||||
|
<Compile Include="RemoteDesktopCommunication\AgentRemoteDesktopConnecitonDetails.cs" />
|
||||||
|
<Compile Include="RemoteDesktopCommunication\ApiResult.cs" />
|
||||||
<Compile Include="TicketOverview\TicketOverviewCountsResponse.cs" />
|
<Compile Include="TicketOverview\TicketOverviewCountsResponse.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ using Newtonsoft.Json;
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
using static C4IT.Logging.cLogManager;
|
using static C4IT.Logging.cLogManager;
|
||||||
using C4IT.Configuration;
|
using FasdCockpitCommunication.RemoteDesktopCommunication;
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
|
|
||||||
namespace C4IT.FASD.Cockpit.Communication
|
namespace C4IT.FASD.Cockpit.Communication
|
||||||
{
|
{
|
||||||
@@ -38,6 +37,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
public cFasdCockpitCommunicationWeb()
|
public cFasdCockpitCommunicationWeb()
|
||||||
{
|
{
|
||||||
M42 = new cF4sdCockpitCommunicationM42Web();
|
M42 = new cF4sdCockpitCommunicationM42Web();
|
||||||
|
RemoteDesktopManager = new AgentRemoteDesktopCommunication();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsDemo() => false;
|
public override bool IsDemo() => false;
|
||||||
@@ -73,7 +73,8 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var http = GetHttpHelper(false);
|
var http = GetHttpHelper(false);
|
||||||
var result = await http.GetHttpJson($"api/CheckConnection", 15000, CancellationToken.None);
|
var _url = $"api/CheckConnection";
|
||||||
|
var result = await http.GetHttpJson(_url, 15000, CancellationToken.None);
|
||||||
|
|
||||||
if (!result.IsOk)
|
if (!result.IsOk)
|
||||||
{
|
{
|
||||||
@@ -81,7 +82,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveApiResultValueJson("CheckConnection", result.Result);
|
if (Debug_apiValues) SaveApiResultValueJson("CheckConnection", result.Result, _url);
|
||||||
var connectionResult = JsonConvert.DeserializeObject<cFasdApiConnectionInfo>(result.Result);
|
var connectionResult = JsonConvert.DeserializeObject<cFasdApiConnectionInfo>(result.Result);
|
||||||
output.ApiConnectionInfo = connectionResult;
|
output.ApiConnectionInfo = connectionResult;
|
||||||
var assembly = Assembly.GetExecutingAssembly();
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
@@ -139,7 +140,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
public static cOneTimePW GetOneTimePw() => new cOneTimePW("OneTimePw", cSecurePassword.Instance);
|
public static cOneTimePW GetOneTimePw() => new cOneTimePW("OneTimePw", cSecurePassword.Instance);
|
||||||
|
|
||||||
public cHttpHelper GetHttpHelper(bool useToken)
|
public static cHttpHelper GetHttpHelper(bool useToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -171,7 +172,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
if (result.IsOk)
|
if (result.IsOk)
|
||||||
{
|
{
|
||||||
SaveApiResultValue("Logon-GetUserIdByAccount", result.Result, "json");
|
if (Debug_apiValues) SaveApiResultValue("Logon-GetUserIdByAccount", result.Result, "json");
|
||||||
output = JsonConvert.DeserializeObject<Guid>(result.Result);
|
output = JsonConvert.DeserializeObject<Guid>(result.Result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,7 +201,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
if (result.IsOk)
|
if (result.IsOk)
|
||||||
{
|
{
|
||||||
if (Debug_apiValues) SaveApiResultValueJson("Logon-Logon", result.Result);
|
if (Debug_apiValues) SaveApiResultValueJson("Logon-Logon", result.Result, _url);
|
||||||
var _retVal = JsonConvert.DeserializeObject<cF4sdUserInfo>(result.Result);
|
var _retVal = JsonConvert.DeserializeObject<cF4sdUserInfo>(result.Result);
|
||||||
return _retVal;
|
return _retVal;
|
||||||
}
|
}
|
||||||
@@ -234,11 +235,12 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
{
|
{
|
||||||
var _payLoad = JsonConvert.SerializeObject(Token);
|
var _payLoad = JsonConvert.SerializeObject(Token);
|
||||||
var http = GetHttpHelper(true);
|
var http = GetHttpHelper(true);
|
||||||
var apiAccessInfo = await http.PostJsonAsync($"api/Logon/RegisterExternalToken", _payLoad, 14000, System.Threading.CancellationToken.None);
|
var _url = $"api/Logon/RegisterExternalToken";
|
||||||
|
var apiAccessInfo = await http.PostJsonAsync(_url, _payLoad, 14000, System.Threading.CancellationToken.None);
|
||||||
if (apiAccessInfo.IsOk)
|
if (apiAccessInfo.IsOk)
|
||||||
{
|
{
|
||||||
var _str = apiAccessInfo.Result;
|
var _str = apiAccessInfo.Result;
|
||||||
if (Debug_apiValues) SaveApiResultValueJson("Logon-RegisterExternalToken", _str);
|
if (Debug_apiValues) SaveApiResultValueJson("Logon-RegisterExternalToken", _str, _url);
|
||||||
var RetVal = JsonConvert.DeserializeObject<cF4SdUserInfoChange>(_str);
|
var RetVal = JsonConvert.DeserializeObject<cF4SdUserInfoChange>(_str);
|
||||||
return RetVal;
|
return RetVal;
|
||||||
}
|
}
|
||||||
@@ -271,9 +273,11 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var http = GetHttpHelper(true);
|
var http = GetHttpHelper(true);
|
||||||
var result = await http.GetHttpJson($"api/Logon/GetAdditionalUserInfo?AccountType={Type}", 5000, CancellationToken.None);
|
var _url = $"api/Logon/GetAdditionalUserInfo?AccountType={Type}";
|
||||||
|
var result = await http.GetHttpJson(_url, 5000, CancellationToken.None);
|
||||||
if (result.IsOk)
|
if (result.IsOk)
|
||||||
{
|
{
|
||||||
|
if (Debug_apiValues) SaveApiResultValueJson("Logon-GetAdditionalUserInfo", result.Result, _url);
|
||||||
var _retVal = JsonConvert.DeserializeObject<cF4SDAdditionalUserInfo>(result.Result);
|
var _retVal = JsonConvert.DeserializeObject<cF4SDAdditionalUserInfo>(result.Result);
|
||||||
return _retVal;
|
return _retVal;
|
||||||
}
|
}
|
||||||
@@ -307,17 +311,17 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var http = GetHttpHelper(false);
|
var http = GetHttpHelper(false);
|
||||||
var result = await http.GetHttpJson("api/F4SDAnalytics/GetF4SDAnalyticsState", 2000, CancellationToken.None);
|
var _url = "api/F4SDAnalytics/GetF4SDAnalyticsState";
|
||||||
|
var result = await http.GetHttpJson(_url, 2000, CancellationToken.None);
|
||||||
|
|
||||||
if (result.IsOk)
|
if (result.IsOk)
|
||||||
{
|
{
|
||||||
if (Debug_apiValues) SaveApiResultValueJson("F4SDAnalytics-GetF4SDAnalyticsState", result.Result);
|
if (Debug_apiValues) SaveApiResultValueJson("F4SDAnalytics-GetF4SDAnalyticsState", result.Result, _url);
|
||||||
output = JsonConvert.DeserializeObject<bool>(result.Result);
|
output = JsonConvert.DeserializeObject<bool>(result.Result);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
apiError = (int)result.Status;
|
apiError = (int)result.Status;
|
||||||
await CheckConnectionStatus?.Invoke();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -353,7 +357,6 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
if (!result.IsOk)
|
if (!result.IsOk)
|
||||||
{
|
{
|
||||||
apiError = (int)result.Status;
|
apiError = (int)result.Status;
|
||||||
await CheckConnectionStatus?.Invoke();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.IsOk;
|
return result.IsOk;
|
||||||
@@ -391,7 +394,6 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
if (!result.IsOk)
|
if (!result.IsOk)
|
||||||
{
|
{
|
||||||
apiError = (int)result.Status;
|
apiError = (int)result.Status;
|
||||||
await CheckConnectionStatus?.Invoke();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
@@ -617,7 +619,6 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
if (!result.IsOk)
|
if (!result.IsOk)
|
||||||
{
|
{
|
||||||
apiError = (int)result.Status;
|
apiError = (int)result.Status;
|
||||||
await CheckConnectionStatus?.Invoke();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,7 +630,6 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
apiError = E.HResult;
|
apiError = E.HResult;
|
||||||
await CheckConnectionStatus?.Invoke();
|
|
||||||
LogException(E);
|
LogException(E);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -875,6 +875,8 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
public override async Task<cFasdApiSearchResultCollection> GetUserSearchResults(string Name, List<string> SIDs)
|
public override async Task<cFasdApiSearchResultCollection> GetUserSearchResults(string Name, List<string> SIDs)
|
||||||
{
|
{
|
||||||
|
const string ApiName = "SearchUserByNameAndSids";
|
||||||
|
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
LogMethodBegin(CM);
|
LogMethodBegin(CM);
|
||||||
|
|
||||||
@@ -895,7 +897,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
strSids = HttpUtility.UrlEncode(strSids);
|
strSids = HttpUtility.UrlEncode(strSids);
|
||||||
|
|
||||||
var strUrl = $"api/SearchUserByNameAndSids?Name={_Name}&SIDs={strSids}";
|
var strUrl = $"api/{ApiName}?Name={_Name}&SIDs={strSids}";
|
||||||
|
|
||||||
var http = GetHttpHelper(true);
|
var http = GetHttpHelper(true);
|
||||||
var result = await http.GetHttpJson(strUrl, 10000, System.Threading.CancellationToken.None);
|
var result = await http.GetHttpJson(strUrl, 10000, System.Threading.CancellationToken.None);
|
||||||
@@ -907,7 +909,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Debug_apiValues) SaveApiResultValueJson("SearchUserByNameAndSids", result.Result, strUrl);
|
if (Debug_apiValues) SaveApiResultValueJson(ApiName, result.Result, strUrl);
|
||||||
var deserializedObject = JsonConvert.DeserializeObject<cFasdApiSearchResultCollection>(result.Result);
|
var deserializedObject = JsonConvert.DeserializeObject<cFasdApiSearchResultCollection>(result.Result);
|
||||||
|
|
||||||
return deserializedObject;
|
return deserializedObject;
|
||||||
@@ -919,7 +921,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (Debug_apiTiming) SaveApiTimingEntry("SearchUserByNameAndSids", timeStart, apiError);
|
if (Debug_apiTiming) SaveApiTimingEntry(ApiName, timeStart, apiError);
|
||||||
LogMethodEnd(CM);
|
LogMethodEnd(CM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -959,6 +961,9 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
public override async Task<cF4sdStagedSearchResultRelationTaskId> StartGatheringRelations(IEnumerable<cFasdApiSearchResultEntry> relatedTo, CancellationToken token)
|
public override async Task<cF4sdStagedSearchResultRelationTaskId> StartGatheringRelations(IEnumerable<cFasdApiSearchResultEntry> relatedTo, CancellationToken token)
|
||||||
{
|
{
|
||||||
|
const string ApiName = "StagedSearchRelations";
|
||||||
|
const string LogName = ApiName + "_Start";
|
||||||
|
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
LogMethodBegin(CM);
|
LogMethodBegin(CM);
|
||||||
|
|
||||||
@@ -967,7 +972,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string url = $"api/StagedSearchRelations?age={cF4SDCockpitXmlConfig.Instance.HealthCardConfig.SearchResultAge}";
|
string url = $"api/{ApiName}?age={cF4SDCockpitXmlConfig.Instance.HealthCardConfig.SearchResultAge}";
|
||||||
string json = JsonConvert.SerializeObject(relatedTo);
|
string json = JsonConvert.SerializeObject(relatedTo);
|
||||||
var http = GetHttpHelper(true);
|
var http = GetHttpHelper(true);
|
||||||
var result = await http.PostJsonAsync(url, json, 5_000, token);
|
var result = await http.PostJsonAsync(url, json, 5_000, token);
|
||||||
@@ -979,6 +984,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Debug_apiValues) SaveApiResultValueJson(LogName, result.Result, url);
|
||||||
return JsonConvert.DeserializeObject<cF4sdStagedSearchResultRelationTaskId>(result.Result);
|
return JsonConvert.DeserializeObject<cF4sdStagedSearchResultRelationTaskId>(result.Result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -989,7 +995,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (Debug_apiTiming) SaveApiTimingEntry("StagedSearchRelationsStart", timeStart, apiError);
|
if (Debug_apiTiming) SaveApiTimingEntry(LogName, timeStart, apiError);
|
||||||
LogMethodEnd(CM);
|
LogMethodEnd(CM);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -997,6 +1003,9 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
public override async Task<cF4sdStagedSearchResultRelations> GetStagedRelations(Guid id, CancellationToken token)
|
public override async Task<cF4sdStagedSearchResultRelations> GetStagedRelations(Guid id, CancellationToken token)
|
||||||
{
|
{
|
||||||
|
const string ApiName = "StagedSearchRelations";
|
||||||
|
const string LogName = ApiName + "_Get";
|
||||||
|
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
LogMethodBegin(CM);
|
LogMethodBegin(CM);
|
||||||
|
|
||||||
@@ -1005,7 +1014,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string url = $"api/StagedSearchRelations/{id}";
|
string url = $"api/{ApiName}/{id}";
|
||||||
var http = GetHttpHelper(true);
|
var http = GetHttpHelper(true);
|
||||||
var result = await http.GetHttpJson(url, 25_000, token, true);
|
var result = await http.GetHttpJson(url, 25_000, token, true);
|
||||||
|
|
||||||
@@ -1016,6 +1025,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Debug_apiValues) SaveApiResultValueJson(LogName, result.Result, url);
|
||||||
return JsonConvert.DeserializeObject<cF4sdStagedSearchResultRelations>(result.Result);
|
return JsonConvert.DeserializeObject<cF4sdStagedSearchResultRelations>(result.Result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -1026,14 +1036,17 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (Debug_apiTiming) SaveApiTimingEntry("StagedSearchRelationsStart", timeStart, apiError);
|
if (Debug_apiTiming) SaveApiTimingEntry(LogName, timeStart, apiError);
|
||||||
LogMethodEnd(CM);
|
LogMethodEnd(CM);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<cF4sdStagedSearchResultRelations> GetRelationResults(Guid relationTaskId, CancellationToken token)
|
public override async Task StopGatheringRelations(Guid id, CancellationToken token)
|
||||||
{
|
{
|
||||||
|
const string ApiName = "StagedSearchRelations";
|
||||||
|
const string LogName = ApiName + "_Stop";
|
||||||
|
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
LogMethodBegin(CM);
|
LogMethodBegin(CM);
|
||||||
|
|
||||||
@@ -1042,18 +1055,21 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string url = $"api/StagedSearchRelations/{relationTaskId}";
|
string url = $"api/{ApiName}/{id}/stop";
|
||||||
var http = GetHttpHelper(true);
|
var http = GetHttpHelper(true);
|
||||||
var result = await http.GetHttpJson(url, 5_000, token, true);
|
var result = await http.GetHttpJson(url, 5_000, token);
|
||||||
|
|
||||||
if (!result.IsOk)
|
if (!result.IsOk)
|
||||||
{
|
{
|
||||||
apiError = (int)result.Status;
|
apiError = (int)result.Status;
|
||||||
await CheckConnectionStatus?.Invoke();
|
if (!token.IsCancellationRequested)
|
||||||
return null;
|
await CheckConnectionStatus?.Invoke();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return JsonConvert.DeserializeObject<cF4sdStagedSearchResultRelations>(result.Result);
|
catch (TaskCanceledException E) when (token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
apiError = E.HResult;
|
||||||
|
LogEntry($"{LogName} was cancelled by token.", LogLevels.Debug);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1063,10 +1079,9 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (Debug_apiTiming) SaveApiTimingEntry("StagedSearchRelations", timeStart, apiError);
|
if (Debug_apiTiming) SaveApiTimingEntry(LogName, timeStart, apiError);
|
||||||
LogMethodEnd(CM);
|
LogMethodEnd(CM);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<List<cF4sdApiSearchResultRelation>> GetSearchResultRelations(enumF4sdSearchResultClass resultType, List<cFasdApiSearchResultEntry> searchResults)
|
public override async Task<List<cF4sdApiSearchResultRelation>> GetSearchResultRelations(enumF4sdSearchResultClass resultType, List<cFasdApiSearchResultEntry> searchResults)
|
||||||
@@ -1101,7 +1116,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
TimeSpan getRelationsDelay = TimeSpan.FromMilliseconds(500);
|
TimeSpan getRelationsDelay = TimeSpan.FromMilliseconds(500);
|
||||||
for (int i = 0; i < maxRetryCount; i++)
|
for (int i = 0; i < maxRetryCount; i++)
|
||||||
{
|
{
|
||||||
var relations = await GetRelationResults(relationTaskId.Id, CancellationToken.None).ConfigureAwait(false);
|
var relations = await GetStagedRelations(relationTaskId.Id, CancellationToken.None).ConfigureAwait(false);
|
||||||
output.AddRange(relations?.Relations);
|
output.AddRange(relations?.Relations);
|
||||||
|
|
||||||
if (relations.IsComplete)
|
if (relations.IsComplete)
|
||||||
@@ -1132,7 +1147,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
#region Ticketübersicht
|
#region Ticketübersicht
|
||||||
|
|
||||||
public override async Task<Dictionary<string, int>> GetTicketOverviewCounts(IEnumerable<string> keys, bool useRoleScope)
|
public override async Task<cF4sdTicketOverviewCountsResult> GetTicketOverviewCounts(IEnumerable<string> keys, bool useRoleScope)
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
LogMethodBegin(CM);
|
LogMethodBegin(CM);
|
||||||
@@ -1167,13 +1182,13 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
await CheckConnectionStatus.Invoke();
|
await CheckConnectionStatus.Invoke();
|
||||||
|
|
||||||
LogEntry($"Error on requesting ticket overview counts ({scope}). Status: {result.Status}", LogLevels.Warning);
|
LogEntry($"Error on requesting ticket overview counts ({scope}). Status: {result.Status}", LogLevels.Warning);
|
||||||
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
return new cF4sdTicketOverviewCountsResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Debug_apiValues) SaveApiResultValueJson("TicketOverview.GetCounts", result.Result, url);
|
if (Debug_apiValues) SaveApiResultValueJson("TicketOverview.GetCounts", result.Result, url);
|
||||||
|
|
||||||
var response = JsonConvert.DeserializeObject<TicketOverviewCountsResponse>(result.Result);
|
var response = JsonConvert.DeserializeObject<TicketOverviewCountsResponse>(result.Result);
|
||||||
return response?.ToDictionary(normalizedKeys) ?? new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
return response?.ToResult(normalizedKeys) ?? new cF4sdTicketOverviewCountsResult();
|
||||||
}
|
}
|
||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
@@ -1189,7 +1204,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
LogMethodEnd(CM);
|
LogMethodEnd(CM);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
return new cF4sdTicketOverviewCountsResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<List<cF4sdApiSearchResultRelation>> GetTicketOverviewRelations(string key, bool useRoleScope, int count)
|
public override async Task<List<cF4sdApiSearchResultRelation>> GetTicketOverviewRelations(string key, bool useRoleScope, int count)
|
||||||
@@ -1500,6 +1515,12 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
public override async Task<bool> Matrix42TicketFinalization(cApiM42Ticket ticketData)
|
public override async Task<bool> Matrix42TicketFinalization(cApiM42Ticket ticketData)
|
||||||
|
{
|
||||||
|
var result = await FinalizeTicketAsync(ticketData);
|
||||||
|
return result?.Success == true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<cTicketFinalizationResult> FinalizeTicketAsync(cApiM42Ticket ticketData)
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
LogMethodBegin(CM);
|
LogMethodBegin(CM);
|
||||||
@@ -1507,7 +1528,6 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
var apiError = 0;
|
var apiError = 0;
|
||||||
var timeStart = DateTime.UtcNow;
|
var timeStart = DateTime.UtcNow;
|
||||||
|
|
||||||
bool output = false;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var http = GetHttpHelper(true);
|
var http = GetHttpHelper(true);
|
||||||
@@ -1517,7 +1537,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
var result = await http.PostJsonAsync(url, payload, 20000, CancellationToken.None);
|
var result = await http.PostJsonAsync(url, payload, 20000, CancellationToken.None);
|
||||||
|
|
||||||
if (result.IsOk)
|
if (result.IsOk)
|
||||||
return true;
|
return ParseTicketFinalizationResult(result.Result, ticketData?.Ticket);
|
||||||
else
|
else
|
||||||
apiError = (int)result.Status;
|
apiError = (int)result.Status;
|
||||||
}
|
}
|
||||||
@@ -1532,7 +1552,102 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
LogMethodEnd(CM);
|
LogMethodEnd(CM);
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return new cTicketFinalizationResult { Success = false };
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static cTicketFinalizationResult ParseTicketFinalizationResult(string response, Guid? fallbackTicketId)
|
||||||
|
{
|
||||||
|
if (fallbackTicketId == Guid.Empty)
|
||||||
|
fallbackTicketId = null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(response))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var token = JToken.Parse(response);
|
||||||
|
if (token.Type == JTokenType.Object)
|
||||||
|
{
|
||||||
|
var result = token.ToObject<cTicketFinalizationResult>();
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
if (result.Success && (!result.TicketId.HasValue || result.TicketId.Value == Guid.Empty))
|
||||||
|
result.TicketId = fallbackTicketId;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (token.Type == JTokenType.String &&
|
||||||
|
Guid.TryParse(token.Value<string>(), out var createdTicketId))
|
||||||
|
{
|
||||||
|
return new cTicketFinalizationResult
|
||||||
|
{
|
||||||
|
Success = true,
|
||||||
|
TicketId = createdTicketId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (JsonException)
|
||||||
|
{
|
||||||
|
if (Guid.TryParse(response.Trim().Trim('"'), out var createdTicketId))
|
||||||
|
{
|
||||||
|
return new cTicketFinalizationResult
|
||||||
|
{
|
||||||
|
Success = true,
|
||||||
|
TicketId = createdTicketId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Older providers returned an empty JSON value for successful updates.
|
||||||
|
return new cTicketFinalizationResult
|
||||||
|
{
|
||||||
|
Success = true,
|
||||||
|
TicketId = fallbackTicketId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<cTicketExternalLinkResult> GetTicketExternalLinkAsync(Guid ticketId, enumTicketExternalOpenMode mode)
|
||||||
|
{
|
||||||
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
|
LogMethodBegin(CM);
|
||||||
|
|
||||||
|
var apiError = 0;
|
||||||
|
var timeStart = DateTime.UtcNow;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (ticketId == Guid.Empty || mode == enumTicketExternalOpenMode.None)
|
||||||
|
return new cTicketExternalLinkResult { Success = false, Mode = enumTicketExternalOpenMode.None };
|
||||||
|
|
||||||
|
var http = GetHttpHelper(true);
|
||||||
|
var url = $"api/Ticketing/GetExternalLink?ticketId={ticketId:D}&mode={Uri.EscapeDataString(mode.ToString())}";
|
||||||
|
var result = await http.GetHttpJson(url, 20000, CancellationToken.None);
|
||||||
|
|
||||||
|
if (result.IsOk)
|
||||||
|
{
|
||||||
|
return JsonConvert.DeserializeObject<cTicketExternalLinkResult>(result.Result)
|
||||||
|
?? new cTicketExternalLinkResult { Success = false, Mode = enumTicketExternalOpenMode.None };
|
||||||
|
}
|
||||||
|
|
||||||
|
apiError = (int)result.Status;
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
apiError = E.HResult;
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (Debug_apiTiming) SaveApiTimingEntry("Ticketing-GetExternalLink", timeStart, apiError);
|
||||||
|
LogMethodEnd(CM);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new cTicketExternalLinkResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Mode = enumTicketExternalOpenMode.None
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<bool> GetAgentApiAccessInfo()
|
public override async Task<bool> GetAgentApiAccessInfo()
|
||||||
@@ -1546,7 +1661,8 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var http = GetHttpHelper(false);
|
var http = GetHttpHelper(false);
|
||||||
var apiAccessInfo = await http.GetHttpJson($"api/GetAgentApiConfiguration", 10000, System.Threading.CancellationToken.None);
|
var _url = $"api/GetAgentApiConfiguration";
|
||||||
|
var apiAccessInfo = await http.GetHttpJson(_url, 10000, System.Threading.CancellationToken.None);
|
||||||
|
|
||||||
if (!apiAccessInfo.IsOk)
|
if (!apiAccessInfo.IsOk)
|
||||||
{
|
{
|
||||||
@@ -1554,7 +1670,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Debug_apiValues) SaveApiResultValueJson("GetAgentApiConfiguration", apiAccessInfo.Result);
|
if (Debug_apiValues) SaveApiResultValueJson("GetAgentApiConfiguration", apiAccessInfo.Result, _url);
|
||||||
var apiConfiguration = JsonConvert.DeserializeObject<cAgentApiConfiguration>(apiAccessInfo.Result);
|
var apiConfiguration = JsonConvert.DeserializeObject<cAgentApiConfiguration>(apiAccessInfo.Result);
|
||||||
if (apiConfiguration != null)
|
if (apiConfiguration != null)
|
||||||
apiConfiguration.ClientSecret = cSecurePassword.Instance.Decode(apiConfiguration.ClientSecret);
|
apiConfiguration.ClientSecret = cSecurePassword.Instance.Decode(apiConfiguration.ClientSecret);
|
||||||
@@ -1570,7 +1686,6 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
apiError = E.HResult;
|
apiError = E.HResult;
|
||||||
await CheckConnectionStatus?.Invoke();
|
|
||||||
LogException(E);
|
LogException(E);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -1593,7 +1708,8 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var http = GetHttpHelper(true);
|
var http = GetHttpHelper(true);
|
||||||
var cockpitconfigResult = await http.GetHttpJson($"api/GetCockpitConfiguration", 10000, System.Threading.CancellationToken.None);
|
var _url = $"api/GetCockpitConfiguration";
|
||||||
|
var cockpitconfigResult = await http.GetHttpJson(_url, 10000, System.Threading.CancellationToken.None);
|
||||||
|
|
||||||
if (!cockpitconfigResult.IsOk)
|
if (!cockpitconfigResult.IsOk)
|
||||||
{
|
{
|
||||||
@@ -1601,7 +1717,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Debug_apiValues) SaveApiResultValueJson("GetCockpitConfiguration", cockpitconfigResult.Result);
|
if (Debug_apiValues) SaveApiResultValueJson("GetCockpitConfiguration", cockpitconfigResult.Result, _url);
|
||||||
var Configuration = JsonConvert.DeserializeObject<cCockpitConfiguration>(cockpitconfigResult.Result);
|
var Configuration = JsonConvert.DeserializeObject<cCockpitConfiguration>(cockpitconfigResult.Result);
|
||||||
if (Configuration?.agentApiConfiguration?.ClientSecret != null)
|
if (Configuration?.agentApiConfiguration?.ClientSecret != null)
|
||||||
Configuration.agentApiConfiguration.ClientSecret = cSecurePassword.Instance.Decode(Configuration.agentApiConfiguration.ClientSecret);
|
Configuration.agentApiConfiguration.ClientSecret = cSecurePassword.Instance.Decode(Configuration.agentApiConfiguration.ClientSecret);
|
||||||
@@ -1616,7 +1732,6 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
apiError = E.HResult;
|
apiError = E.HResult;
|
||||||
await CheckConnectionStatus?.Invoke();
|
|
||||||
LogException(E);
|
LogException(E);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -1639,7 +1754,8 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var http = GetHttpHelper(false);
|
var http = GetHttpHelper(false);
|
||||||
var result = await http.GetHttpJson("api/QuickAction/GetQuickActionList", 15000, CancellationToken.None);
|
var _url = "api/QuickAction/GetQuickActionList";
|
||||||
|
var result = await http.GetHttpJson(_url, 15000, CancellationToken.None);
|
||||||
|
|
||||||
if (!result.IsOk)
|
if (!result.IsOk)
|
||||||
{
|
{
|
||||||
@@ -1652,6 +1768,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
}
|
}
|
||||||
if (result.Result is string jsonString && !string.IsNullOrWhiteSpace(jsonString))
|
if (result.Result is string jsonString && !string.IsNullOrWhiteSpace(jsonString))
|
||||||
{
|
{
|
||||||
|
if (Debug_apiValues) SaveApiResultValueJson("GetQuickActionsOfServer", result.Result, _url);
|
||||||
return JsonConvert.DeserializeObject<List<string>>(result.Result);
|
return JsonConvert.DeserializeObject<List<string>>(result.Result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2041,10 +2158,17 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
private void SaveApiResultValueJson(string ApiName, string json, string comment = null)
|
private void SaveApiResultValueJson(string ApiName, string json, string comment = null)
|
||||||
{
|
{
|
||||||
List<string> comments = null;
|
try
|
||||||
if (comment != null)
|
{
|
||||||
comments = new List<string>() { comment };
|
List<string> comments = null;
|
||||||
SaveApiResultValueJson(ApiName, json, comments);
|
if (comment != null)
|
||||||
|
comments = new List<string>() { comment };
|
||||||
|
SaveApiResultValueJson(ApiName, json, comments);
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveApiResultValueJson(string ApiName, string json, List<string> comment)
|
private void SaveApiResultValueJson(string ApiName, string json, List<string> comment)
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
using C4IT.FASD.Base;
|
||||||
|
using C4IT.FASD.Cockpit.Communication;
|
||||||
|
using C4IT.FASD.Communication.Agent;
|
||||||
|
using C4IT.HTTP;
|
||||||
|
using FasdCockpitBase;
|
||||||
|
using FasdCockpitBase.Models.RemoteDesktopConnection;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace FasdCockpitCommunication.RemoteDesktopCommunication
|
||||||
|
{
|
||||||
|
internal class AgentRemoteDesktopCommunication : RemoteDesktopCommunicationBase
|
||||||
|
{
|
||||||
|
private readonly HttpClient _httpClient = new HttpClient();
|
||||||
|
|
||||||
|
public AgentRemoteDesktopCommunication()
|
||||||
|
{
|
||||||
|
_httpClient.BaseAddress = new Uri(cFasdCockpitMachineConfiguration.Instance.ServerUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<T> InitiateConnection<T>(IRemoteDesktopClientInfo clientInfo, bool isElevated, CancellationToken token)
|
||||||
|
{
|
||||||
|
cHttpHelper httpHelper = cFasdCockpitCommunicationWeb.GetHttpHelper(false);
|
||||||
|
string json = JsonConvert.SerializeObject(clientInfo);
|
||||||
|
string path = "api/RemoteDesktop/Initiate";
|
||||||
|
|
||||||
|
if (isElevated)
|
||||||
|
path += "?isElevated=true";
|
||||||
|
|
||||||
|
cHttpResult result = await httpHelper.PostJsonAsync(path, json, 30_000, token);
|
||||||
|
return JsonConvert.DeserializeObject<T>(result.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<RemoteDesktopConnectionStatusResult> GetConnectionStatus(Guid connectionId, CancellationToken token)
|
||||||
|
{
|
||||||
|
cHttpHelper http = cFasdCockpitCommunicationWeb.GetHttpHelper(false);
|
||||||
|
string path = $"api/RemoteDesktop/{connectionId}/Status";
|
||||||
|
cHttpResult result = await http.GetHttpJson(path, 15_000, token, true);
|
||||||
|
|
||||||
|
if (!result.IsOk)
|
||||||
|
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Unknown);
|
||||||
|
|
||||||
|
AgentRemoteConnectionStatusDto connectionStatus = JsonConvert.DeserializeObject<AgentRemoteConnectionStatusDto>(result.Result);
|
||||||
|
return GetGeneralConnectionStatus(connectionStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RemoteDesktopConnectionStatusResult GetGeneralConnectionStatus(AgentRemoteConnectionStatusDto connectionStatus)
|
||||||
|
{
|
||||||
|
switch (connectionStatus.Status)
|
||||||
|
{
|
||||||
|
case AgentRemoteConnectionStatus.New:
|
||||||
|
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Initiated);
|
||||||
|
case AgentRemoteConnectionStatus.Accepted:
|
||||||
|
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Accepted);
|
||||||
|
case AgentRemoteConnectionStatus.DisconnectedByHelpdesk:
|
||||||
|
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Finished);
|
||||||
|
case AgentRemoteConnectionStatus.DisconnectedByClient:
|
||||||
|
case AgentRemoteConnectionStatus.Failed:
|
||||||
|
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Canceled);
|
||||||
|
case AgentRemoteConnectionStatus.Unknown:
|
||||||
|
default:
|
||||||
|
return new RemoteDesktopConnectionStatusResult(RemoteDesktopConnectionStatus.Unknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task StopConnection(Guid connectionId, CancellationToken token)
|
||||||
|
{
|
||||||
|
cHttpHelper http = cFasdCockpitCommunicationWeb.GetHttpHelper(false);
|
||||||
|
string path = $"api/RemoteDesktop/{connectionId}/Stop";
|
||||||
|
await http.DeleteAsync(path, 15_000, token, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<HealthInformation> GetHealth(CancellationToken token)
|
||||||
|
{
|
||||||
|
cHttpHelper http = cFasdCockpitCommunicationWeb.GetHttpHelper(false);
|
||||||
|
string path = $"api/RemoteDesktop/health";
|
||||||
|
cHttpResult result = await http.GetHttpJson(path, 10_000, token, true);
|
||||||
|
|
||||||
|
if (!result.IsOk)
|
||||||
|
return new HealthInformation(HealthStatus.unhealthy);
|
||||||
|
|
||||||
|
return JsonConvert.DeserializeObject<HealthInformation>(result.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<bool> IsRemoteDesktopCommunicationAvailable()
|
||||||
|
{
|
||||||
|
cHttpHelper http = cFasdCockpitCommunicationWeb.GetHttpHelper(false);
|
||||||
|
string path = $"api/RemoteDesktop/IsActive";
|
||||||
|
cHttpResult result = await http.GetHttpJson(path, 5_000, CancellationToken.None, false);
|
||||||
|
|
||||||
|
if (!result.IsOk)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool isRemoteViewerActive = JsonConvert.DeserializeObject<bool>(result.Result); ;
|
||||||
|
if (!isRemoteViewerActive)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return await base.IsRemoteDesktopCommunicationAvailable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AgentRemoteClientInfo : IRemoteDesktopClientInfo
|
||||||
|
{
|
||||||
|
[JsonProperty("orgCode")]
|
||||||
|
public int OrganisationCode { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("deviceCode")]
|
||||||
|
public int DeviceCode { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("accountCode")]
|
||||||
|
public int AccountCode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using FasdCockpitBase.Models.RemoteDesktopConnection;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace FasdCockpitCommunication.RemoteDesktopCommunication
|
||||||
|
{
|
||||||
|
public class AgentRemoteDesktopConnecitonDetails : ApiResult, IRemoteDesktopConnectionDetails
|
||||||
|
{
|
||||||
|
[JsonProperty("connectionId")]
|
||||||
|
public Guid ConnectionId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("phoenixServiceUrl")]
|
||||||
|
public Uri PhoenixServiceUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("secret")]
|
||||||
|
public string Secret { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace FasdCockpitCommunication.RemoteDesktopCommunication
|
||||||
|
{
|
||||||
|
public class ApiResult
|
||||||
|
{
|
||||||
|
[JsonProperty("errors")]
|
||||||
|
public IList<ApiError> Errors { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ApiError
|
||||||
|
{
|
||||||
|
[JsonProperty("code")]
|
||||||
|
public string Code { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("message")]
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using C4IT.FASD.Cockpit.Communication;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace FasdCockpitCommunication.TicketOverview
|
namespace FasdCockpitCommunication.TicketOverview
|
||||||
@@ -10,7 +11,10 @@ namespace FasdCockpitCommunication.TicketOverview
|
|||||||
[JsonProperty("counts")]
|
[JsonProperty("counts")]
|
||||||
public Dictionary<string, int> Counts { get; set; } = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
public Dictionary<string, int> Counts { get; set; } = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public Dictionary<string, int> ToDictionary(IEnumerable<string> expectedKeys)
|
[JsonProperty("capabilities")]
|
||||||
|
public TicketOverviewCapabilitiesResponse Capabilities { get; set; } = new TicketOverviewCapabilitiesResponse();
|
||||||
|
|
||||||
|
public cF4sdTicketOverviewCountsResult ToResult(IEnumerable<string> expectedKeys)
|
||||||
{
|
{
|
||||||
var comparer = StringComparer.OrdinalIgnoreCase;
|
var comparer = StringComparer.OrdinalIgnoreCase;
|
||||||
var output = new Dictionary<string, int>(comparer);
|
var output = new Dictionary<string, int>(comparer);
|
||||||
@@ -28,7 +32,7 @@ namespace FasdCockpitCommunication.TicketOverview
|
|||||||
output[key] = 0;
|
output[key] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return CreateResult(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Counts != null)
|
if (Counts != null)
|
||||||
@@ -42,7 +46,25 @@ namespace FasdCockpitCommunication.TicketOverview
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return CreateResult(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
private cF4sdTicketOverviewCountsResult CreateResult(Dictionary<string, int> counts)
|
||||||
|
{
|
||||||
|
return new cF4sdTicketOverviewCountsResult
|
||||||
|
{
|
||||||
|
Counts = counts,
|
||||||
|
Capabilities = new cF4sdTicketOverviewCapabilities
|
||||||
|
{
|
||||||
|
TicketAndServiceRequestsEnabled = Capabilities?.TicketAndServiceRequestsEnabled ?? true
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal sealed class TicketOverviewCapabilitiesResponse
|
||||||
|
{
|
||||||
|
[JsonProperty("ticketAndServiceRequestsEnabled")]
|
||||||
|
public bool TicketAndServiceRequestsEnabled { get; set; } = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.2" newVersion="10.0.0.2" />
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.3" newVersion="10.0.0.3" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net472" />
|
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
|
||||||
</packages>
|
</packages>
|
||||||
@@ -12,12 +12,31 @@
|
|||||||
<TicketConfiguration>
|
<TicketConfiguration>
|
||||||
<DisableAutomaticTimeTracking Policy="Mandatory" Value="true" />
|
<DisableAutomaticTimeTracking Policy="Mandatory" Value="true" />
|
||||||
<CompletitionPolicy Policy="Mandatory" Value="IfRequired" />
|
<CompletitionPolicy Policy="Mandatory" Value="IfRequired" />
|
||||||
|
<UseSimplifiedCaseCompletionDialog Policy="Mandatory" Value="false" />
|
||||||
|
<SimplifiedCaseCompletionTicketOpenMode Policy="Default" Value="Preview" />
|
||||||
<NotesMandatory Policy="Mandatory" Value="true" />
|
<NotesMandatory Policy="Mandatory" Value="true" />
|
||||||
<ShowOverview Policy="Mandatory" Value="true" />
|
<ShowOverview Policy="Mandatory" Value="true" />
|
||||||
<OpenActivitiesExternally Policy="Mandatory" Value="false">
|
<TicketProcessing Policy="Mandatory" Value="both">
|
||||||
<OpenActivityOverride ActivityType="SPSActivityTypeTicket" Value="false" />
|
<TicketTypeProcessing Type="Ticket" Value="intern" />
|
||||||
<OpenActivityOverride ActivityType="SPSActivityTypeServiceRequest" Value="true" />
|
<TicketTypeProcessing Type="UnclassifiedTicket" Value="intern" />
|
||||||
</OpenActivitiesExternally>
|
<TicketTypeProcessing Type="Incident" Value="intern" />
|
||||||
|
</TicketProcessing>
|
||||||
|
<TicketFilters>
|
||||||
|
<Filter Provider="Matrix42" Field="Queue" Enabled="false" Match="include" EmptyHandling="include">
|
||||||
|
<Value ID="2a7e8099-3d57-f011-1988-00155d320605" Name="HR" />
|
||||||
|
<Value ID="2a7a8099-3d47-f011-1988-00155d320505" Name="FM" />
|
||||||
|
</Filter>
|
||||||
|
<Filter Field="AssignmentGroup" Enabled="false" Match="include" EmptyHandling="exclude">
|
||||||
|
<Value ID="0a76de08-136c-764a-b410-5610e8076712" Name="HR Service Desk Agent" />
|
||||||
|
<Value ID="0b76de08-8668-a026-b410-5610e8076f95" Name="HR-Manager" />
|
||||||
|
<Value ID="0a76de08-d589-4c94-b410-5610e8076919" Name="HR-Spezialist" />
|
||||||
|
<Value ID="e87dde08-235c-04e5-b410-562b64035575" Name="Facility-Koordinator" />
|
||||||
|
</Filter>
|
||||||
|
<Filter Provider="Matrix42" Field="Workspace" Enabled="false" Match="include" EmptyHandling="exclude">
|
||||||
|
<Value ID="1676de08-27f3-550c-b410-5610e807aa02" Name="HR Service Management" />
|
||||||
|
<Value ID="ed7dde08-199e-c27b-b410-562b64037aa1" Name="Gebäudemanagement" />
|
||||||
|
</Filter>
|
||||||
|
</TicketFilters>
|
||||||
<OverviewPollingPersonal Policy="Mandatory" Value="10" />
|
<OverviewPollingPersonal Policy="Mandatory" Value="10" />
|
||||||
<OverviewPollingRole Policy="Mandatory" Value="5" />
|
<OverviewPollingRole Policy="Mandatory" Value="5" />
|
||||||
</TicketConfiguration>
|
</TicketConfiguration>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
param(
|
param(
|
||||||
$ComputerName = "",
|
$ComputerName = "",
|
||||||
$AI_Prompt = "how can this be fixed? Answer in german",
|
$AI_Prompt = "how can this be fixed? Answer in german",
|
||||||
$AI_Key = "AIzaSyCotStXy-4lkxCc5ii4NtQEG-jJM6Cnzkc"
|
$AI_Key = "AIzaSyBhXz8EU0jTyaZ4e_CLJB5mn7SMPjlJrSw"
|
||||||
)
|
)
|
||||||
$ServerAddress = $env:COMPUTERNAME
|
$ServerAddress = $env:COMPUTERNAME
|
||||||
$ServerPort = 7000
|
$ServerPort = 7000
|
||||||
@@ -70,22 +70,22 @@
|
|||||||
|
|
||||||
# get the execution directory
|
# get the execution directory
|
||||||
$dirExe = $PSScriptRoot
|
$dirExe = $PSScriptRoot
|
||||||
if (-not (Test-Path -Path "$dirExe\Phoenix.Viewer\Phoenix.Viewer.exe" -PathType Leaf))
|
if (-not (Test-Path -Path "$env:ProgramFiles\EgoMind\Phoenix\Viewer\Phoenix.Viewer.exe" -PathType Leaf))
|
||||||
{
|
{
|
||||||
$dirExe = (Get-Location).Path
|
$dirExe = (Get-Location).Path
|
||||||
$dirExe = "$dirExe\PhoenixDemo"
|
$dirExe = "$dirExe\PhoenixDemo"
|
||||||
}
|
}
|
||||||
if (-not (Test-Path -Path "$dirExe\Phoenix.Viewer\Phoenix.Viewer.exe" -PathType Leaf))
|
if (-not (Test-Path -Path "$env:ProgramFiles\EgoMind\Phoenix\Viewer\Phoenix.Viewer.exe" -PathType Leaf))
|
||||||
{
|
{
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
# save server address to config file
|
# save server address to config file
|
||||||
$jsonConfig = Get-Content "$dirExe\Phoenix.Viewer\appSettings.json" | ConvertFrom-Json
|
$jsonConfig = Get-Content "$env:ProgramFiles\EgoMind\Phoenix\Viewer\appSettings.json" | ConvertFrom-Json
|
||||||
$jsonConfig.HostOptions.Host = "http://${ServerAddress}:${ServerPort}"
|
$jsonConfig.HostOptions.Host = "http://${ServerAddress}:${ServerPort}"
|
||||||
$jsonConfig.AIOptions.Prompt = $AI_Prompt
|
$jsonConfig.AIOptions.Prompt = $AI_Prompt
|
||||||
$jsonConfig.AIOptions.ApiKey = $AI_Key
|
$jsonConfig.AIOptions.ApiKey = $AI_Key
|
||||||
$jsonConfig | ConvertTo-Json -depth 100 | Out-File "$dirExe\Phoenix.Viewer\appSettings.json" -Encoding utf8
|
$jsonConfig | ConvertTo-Json -depth 100 | Out-File "$env:ProgramFiles\EgoMind\Phoenix\Viewer\appSettings.json" -Encoding utf8
|
||||||
|
|
||||||
# define the argumet list
|
# define the argumet list
|
||||||
$args = @("--config appSettings.json")
|
$args = @("--config appSettings.json")
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
# start the viewer
|
# start the viewer
|
||||||
$procViewer = Start-Process -WorkingDirectory "$dirExe\Phoenix.Viewer" -WindowStyle Normal -FilePath "$dirExe\Phoenix.Viewer\Phoenix.Viewer.exe" -PassThru -ArgumentList $args
|
$procViewer = Start-Process -WorkingDirectory "$env:ProgramFiles\EgoMind\Phoenix\Viewer" -WindowStyle Normal -FilePath "$env:ProgramFiles\EgoMind\Phoenix\Viewer\Phoenix.Viewer.exe" -PassThru -ArgumentList $args
|
||||||
|
|
||||||
# get & resize the viewer main window
|
# get & resize the viewer main window
|
||||||
add-type -typedefinition "using System;`n using System.Runtime.InteropServices;`n public class Windows { [DllImport(`"user32.dll`")] [return: MarshalAs(UnmanagedType.Bool)] public extern static bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw); }"
|
add-type -typedefinition "using System;`n using System.Runtime.InteropServices;`n public class Windows { [DllImport(`"user32.dll`")] [return: MarshalAs(UnmanagedType.Bool)] public extern static bool MoveWindow(IntPtr handle, int x, int y, int width, int height, bool redraw); }"
|
||||||
@@ -500,7 +500,7 @@
|
|||||||
</QuickAction-Demo>
|
</QuickAction-Demo>
|
||||||
|
|
||||||
|
|
||||||
<QuickAction-Demo InformationClass="VirtuelSession" Name="Session Logoff" Section="Citrix" RunImmediate="false" CheckNamedParameter="VirtualSessionStatus" SimulatedClientConnect="1" SimulatedRuntime="1">
|
<QuickAction-Demo InformationClass="VirtualSession" Name="Session Logoff" Section="Citrix" RunImmediate="false" CheckNamedParameter="VirtualSessionStatus" SimulatedClientConnect="1" SimulatedRuntime="1">
|
||||||
<Name Lang="DE">Session abmelden</Name>
|
<Name Lang="DE">Session abmelden</Name>
|
||||||
<Icon IconType="material" Name="ic_vpn_key" />
|
<Icon IconType="material" Name="ic_vpn_key" />
|
||||||
<CheckNamedParameterValues>
|
<CheckNamedParameterValues>
|
||||||
@@ -508,7 +508,7 @@
|
|||||||
</CheckNamedParameterValues>
|
</CheckNamedParameterValues>
|
||||||
<DemoResult Result="finished">[{"":"Erfolgreich von Session abgemeldet"}]</DemoResult>
|
<DemoResult Result="finished">[{"":"Erfolgreich von Session abgemeldet"}]</DemoResult>
|
||||||
</QuickAction-Demo>
|
</QuickAction-Demo>
|
||||||
<QuickAction-Demo InformationClass="VirtuelSession" Name="Session Hidden" Section="Citrix" RunImmediate="false" CheckNamedParameter="VirtualSessionStatus" SimulatedClientConnect="1" SimulatedRuntime="1">
|
<QuickAction-Demo InformationClass="VirtualSession" Name="Session Hidden" Section="Citrix" RunImmediate="false" CheckNamedParameter="VirtualSessionStatus" SimulatedClientConnect="1" SimulatedRuntime="1">
|
||||||
<Name Lang="DE">Session verstecken</Name>
|
<Name Lang="DE">Session verstecken</Name>
|
||||||
<Icon IconType="material" Name="ic_vpn_key" />
|
<Icon IconType="material" Name="ic_vpn_key" />
|
||||||
<CheckNamedParameterValues>
|
<CheckNamedParameterValues>
|
||||||
@@ -516,7 +516,7 @@
|
|||||||
</CheckNamedParameterValues>
|
</CheckNamedParameterValues>
|
||||||
<DemoResult Result="finished">[{"":"Session erfolgreich versteckt"}]</DemoResult>
|
<DemoResult Result="finished">[{"":"Session erfolgreich versteckt"}]</DemoResult>
|
||||||
</QuickAction-Demo>
|
</QuickAction-Demo>
|
||||||
<QuickAction-Demo InformationClass="VirtuelSession" Name="Send message to Session" Section="Citrix" RunImmediate="false" CheckNamedParameter="VirtualSessionStatus" SimulatedClientConnect="1" SimulatedRuntime="1">
|
<QuickAction-Demo InformationClass="VirtualSession" Name="Send message to Session" Section="Citrix" RunImmediate="false" CheckNamedParameter="VirtualSessionStatus" SimulatedClientConnect="1" SimulatedRuntime="1">
|
||||||
<Name Lang="DE">Sende Nachricht an Session</Name>
|
<Name Lang="DE">Sende Nachricht an Session</Name>
|
||||||
<Icon IconType="material" Name="ic_vpn_key" />
|
<Icon IconType="material" Name="ic_vpn_key" />
|
||||||
<CheckNamedParameterValues>
|
<CheckNamedParameterValues>
|
||||||
@@ -526,7 +526,7 @@
|
|||||||
</QuickAction-Demo>
|
</QuickAction-Demo>
|
||||||
|
|
||||||
|
|
||||||
<QuickAction-Demo InformationClass="VirtuelSession" Name="Session Hidden" Section="Citrix" RunImmediate="false" CheckNamedParameter="VirtualSessionStatus" SimulatedClientConnect="1" SimulatedRuntime="1">
|
<QuickAction-Demo InformationClass="VirtualSession" Name="Session Hidden" Section="Citrix" RunImmediate="false" CheckNamedParameter="VirtualSessionStatus" SimulatedClientConnect="1" SimulatedRuntime="1">
|
||||||
<Name Lang="DE">Session verstecken</Name>
|
<Name Lang="DE">Session verstecken</Name>
|
||||||
<Icon IconType="material" Name="ic_vpn_key" />
|
<Icon IconType="material" Name="ic_vpn_key" />
|
||||||
<CheckNamedParameterValues>
|
<CheckNamedParameterValues>
|
||||||
@@ -534,7 +534,7 @@
|
|||||||
</CheckNamedParameterValues>
|
</CheckNamedParameterValues>
|
||||||
<DemoResult Result="finished">[{"":"Session erfolgreich versteckt"}]</DemoResult>
|
<DemoResult Result="finished">[{"":"Session erfolgreich versteckt"}]</DemoResult>
|
||||||
</QuickAction-Demo>
|
</QuickAction-Demo>
|
||||||
<QuickAction-Demo InformationClass="VirtuelSession" Name="Send message to Session" Section="Citrix" RunImmediate="false" CheckNamedParameter="VirtualSessionStatus" SimulatedClientConnect="1" SimulatedRuntime="1">
|
<QuickAction-Demo InformationClass="VirtualSession" Name="Send message to Session" Section="Citrix" RunImmediate="false" CheckNamedParameter="VirtualSessionStatus" SimulatedClientConnect="1" SimulatedRuntime="1">
|
||||||
<Name Lang="DE">Sende Nachricht an Session</Name>
|
<Name Lang="DE">Sende Nachricht an Session</Name>
|
||||||
<Icon IconType="material" Name="ic_vpn_key" />
|
<Icon IconType="material" Name="ic_vpn_key" />
|
||||||
<CheckNamedParameterValues>
|
<CheckNamedParameterValues>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<xs:enumeration value="User" />
|
<xs:enumeration value="User" />
|
||||||
<xs:enumeration value="Computer" />
|
<xs:enumeration value="Computer" />
|
||||||
<xs:enumeration value="Ticket" />
|
<xs:enumeration value="Ticket" />
|
||||||
<xs:enumeration value="VirtuelSession" />
|
<xs:enumeration value="VirtualSession" />
|
||||||
<xs:enumeration value="MobileDevice" />
|
<xs:enumeration value="MobileDevice" />
|
||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
@@ -197,6 +197,16 @@
|
|||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:element name="QuickAction-Native" substitutionGroup="QuickAction">
|
||||||
|
<xs:complexType >
|
||||||
|
<xs:complexContent>
|
||||||
|
<xs:extension base="QuickAction">
|
||||||
|
<xs:attribute name="NativeName" type="xs:NCName" use="required" />
|
||||||
|
</xs:extension>
|
||||||
|
</xs:complexContent>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
<xs:complexType name="QuickAction-Local" abstract="true">
|
<xs:complexType name="QuickAction-Local" abstract="true">
|
||||||
<xs:complexContent>
|
<xs:complexContent>
|
||||||
<xs:extension base="QuickAction">
|
<xs:extension base="QuickAction">
|
||||||
@@ -249,7 +259,7 @@
|
|||||||
<xs:extension base="QuickAction-Remote">
|
<xs:extension base="QuickAction-Remote">
|
||||||
<xs:attribute name="Category" use="optional" />
|
<xs:attribute name="Category" use="optional" />
|
||||||
<xs:attribute name="Action" use="optional" />
|
<xs:attribute name="Action" use="optional" />
|
||||||
<xs:attribute name="ParamaterType" use="optional" />
|
<xs:attribute name="ParameterType" use="optional" />
|
||||||
</xs:extension>
|
</xs:extension>
|
||||||
</xs:complexContent>
|
</xs:complexContent>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static cF4SDTicket ConvertToTicket(DemoTicketRecord record)
|
private static cF4SDTicketDemo ConvertToTicket(DemoTicketRecord record)
|
||||||
{
|
{
|
||||||
var status = enumTicketStatus.New;
|
var status = enumTicketStatus.New;
|
||||||
if (!string.IsNullOrWhiteSpace(record.StatusId) && Enum.TryParse(record.StatusId, true, out enumTicketStatus parsedStatus))
|
if (!string.IsNullOrWhiteSpace(record.StatusId) && Enum.TryParse(record.StatusId, true, out enumTicketStatus parsedStatus))
|
||||||
@@ -226,7 +226,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
var detail = record.Detail ?? new DemoTicketDetail();
|
var detail = record.Detail ?? new DemoTicketDetail();
|
||||||
var createdAt = record.CreatedAt == default ? DateTime.UtcNow : record.CreatedAt;
|
var createdAt = record.CreatedAt == default ? DateTime.UtcNow : record.CreatedAt;
|
||||||
|
|
||||||
var ticket = new cF4SDTicket
|
var ticket = new cF4SDTicketDemo
|
||||||
{
|
{
|
||||||
Id = record.TicketId,
|
Id = record.TicketId,
|
||||||
Name = record.DisplayName,
|
Name = record.DisplayName,
|
||||||
@@ -243,9 +243,9 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
CreationDate = createdAt.ToLocalTime(),
|
CreationDate = createdAt.ToLocalTime(),
|
||||||
CreationDaysSinceNow = Math.Max(0, (int)(DateTime.UtcNow - createdAt).TotalDays),
|
CreationDaysSinceNow = Math.Max(0, (int)(DateTime.UtcNow - createdAt).TotalDays),
|
||||||
Priority = detail.Priority ?? 0,
|
Priority = detail.Priority ?? 0,
|
||||||
CreationSource = cF4SDTicket.enumTicketCreationSource.F4SD,
|
CreationSource = cF4SDTicketDemo.enumTicketCreationSource.F4SD,
|
||||||
DirectLinks = new Dictionary<string, string>(),
|
DirectLinks = new Dictionary<string, string>(),
|
||||||
JournalItems = new List<cF4SDTicket.cTicketJournalItem>()
|
JournalItems = new List<cF4SDTicketDemo.cTicketJournalItemDemo>()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (detail.Journal != null)
|
if (detail.Journal != null)
|
||||||
@@ -253,7 +253,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
foreach (var entry in detail.Journal)
|
foreach (var entry in detail.Journal)
|
||||||
{
|
{
|
||||||
var journalCreation = entry?.CreationDate ?? createdAt;
|
var journalCreation = entry?.CreationDate ?? createdAt;
|
||||||
ticket.JournalItems.Add(new cF4SDTicket.cTicketJournalItem
|
ticket.JournalItems.Add(new cF4SDTicketDemo.cTicketJournalItemDemo
|
||||||
{
|
{
|
||||||
Header = entry.Header,
|
Header = entry.Header,
|
||||||
Description = entry.Description,
|
Description = entry.Description,
|
||||||
@@ -268,7 +268,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return ticket;
|
return ticket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task<Dictionary<string, int>> GetTicketOverviewCounts(IEnumerable<string> keys, bool useRoleScope)
|
public override Task<cF4sdTicketOverviewCountsResult> GetTicketOverviewCounts(IEnumerable<string> keys, bool useRoleScope)
|
||||||
{
|
{
|
||||||
var scopeKey = useRoleScope ? "Role" : "Personal";
|
var scopeKey = useRoleScope ? "Role" : "Personal";
|
||||||
var comparer = StringComparer.OrdinalIgnoreCase;
|
var comparer = StringComparer.OrdinalIgnoreCase;
|
||||||
@@ -299,7 +299,10 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult(result);
|
return Task.FromResult(new cF4sdTicketOverviewCountsResult
|
||||||
|
{
|
||||||
|
Counts = result
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<List<cF4sdApiSearchResultRelation>> GetTicketOverviewRelations(string key, bool useRoleScope, int count)
|
public override async Task<List<cF4sdApiSearchResultRelation>> GetTicketOverviewRelations(string key, bool useRoleScope, int count)
|
||||||
@@ -374,7 +377,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private cF4SDTicket FindTicketForOverviewRelation(DemoTicketRecord definition)
|
private cF4SDTicketDemo FindTicketForOverviewRelation(DemoTicketRecord definition)
|
||||||
{
|
{
|
||||||
if (definition == null || definition.TicketId == Guid.Empty)
|
if (definition == null || definition.TicketId == Guid.Empty)
|
||||||
return null;
|
return null;
|
||||||
@@ -1470,17 +1473,17 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private cF4SDTicket GetTicketFromWriteParameter(cF4SDWriteParameters writeParams)
|
private cF4SDTicketDemo GetTicketFromWriteParameter(cF4SDWriteParameters writeParams)
|
||||||
{
|
{
|
||||||
cF4SDTicket output = null;
|
cF4SDTicketDemo output = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
output = new cF4SDTicket()
|
output = new cF4SDTicketDemo()
|
||||||
{
|
{
|
||||||
Id = writeParams.id,
|
Id = writeParams.id,
|
||||||
DirectLinks = new Dictionary<string, string>(),
|
DirectLinks = new Dictionary<string, string>(),
|
||||||
JournalItems = new List<cF4SDTicket.cTicketJournalItem>()
|
JournalItems = new List<cF4SDTicketDemo.cTicketJournalItemDemo>()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (writeParams.Values.TryGetValue("Summary", out var summary))
|
if (writeParams.Values.TryGetValue("Summary", out var summary))
|
||||||
@@ -1505,7 +1508,7 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
output.ActivityType = activityType?.ToString()?.Trim();
|
output.ActivityType = activityType?.ToString()?.Trim();
|
||||||
|
|
||||||
if (writeParams.Values.TryGetValue("CreationSource", out var creationSourceObj))
|
if (writeParams.Values.TryGetValue("CreationSource", out var creationSourceObj))
|
||||||
if (Enum.TryParse(creationSourceObj.ToString(), out cF4SDTicket.enumTicketCreationSource creationSource))
|
if (Enum.TryParse(creationSourceObj.ToString(), out cF4SDTicketDemo.enumTicketCreationSource creationSource))
|
||||||
output.CreationSource = creationSource;
|
output.CreationSource = creationSource;
|
||||||
|
|
||||||
if (writeParams.Values.TryGetValue("Status", out var statusObj))
|
if (writeParams.Values.TryGetValue("Status", out var statusObj))
|
||||||
@@ -1588,13 +1591,13 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private cF4SDTicket.cTicketJournalItem GetJournalItemFromWriteParameter(cF4SDWriteParameters writeParams)
|
private cF4SDTicketDemo.cTicketJournalItemDemo GetJournalItemFromWriteParameter(cF4SDWriteParameters writeParams)
|
||||||
{
|
{
|
||||||
cF4SDTicket.cTicketJournalItem output = null;
|
cF4SDTicketDemo.cTicketJournalItemDemo output = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
output = new cF4SDTicket.cTicketJournalItem();
|
output = new cF4SDTicketDemo.cTicketJournalItemDemo();
|
||||||
|
|
||||||
if (writeParams.Values.TryGetValue("Header", out var header))
|
if (writeParams.Values.TryGetValue("Header", out var header))
|
||||||
output.Header = header.ToString();
|
output.Header = header.ToString();
|
||||||
@@ -1681,10 +1684,10 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
|
|
||||||
public override Task<bool> Matrix42TicketFinalization(cApiM42Ticket ticketData) => Task.FromResult(true);
|
public override Task<bool> Matrix42TicketFinalization(cApiM42Ticket ticketData) => Task.FromResult(true);
|
||||||
|
|
||||||
private async Task<List<cF4SDTicket>> GetDemoTicketData(cF4sdHealthCardRawDataRequest requestData)
|
private async Task<List<cF4SDTicketDemo>> GetDemoTicketData(cF4sdHealthCardRawDataRequest requestData)
|
||||||
{
|
{
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
var output = new List<cF4SDTicket>();
|
var output = new List<cF4SDTicketDemo>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var selectedData = MockupData.FirstOrDefault(data => requestData.Identities.Any(identity => identity.Id == data.SampleDataId));
|
var selectedData = MockupData.FirstOrDefault(data => requestData.Identities.Any(identity => identity.Id == data.SampleDataId));
|
||||||
@@ -1702,16 +1705,16 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<cF4SDTicketSummary>> GetTicketSummaries(cF4sdHealthCardRawDataRequest requestData)
|
public async Task<List<cF4SDTicketSummaryDemo>> GetTicketSummaries(cF4sdHealthCardRawDataRequest requestData)
|
||||||
{
|
{
|
||||||
|
|
||||||
var output = new List<cF4SDTicketSummary>();
|
var output = new List<cF4SDTicketSummaryDemo>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var demoTickets = await GetDemoTicketData(requestData);
|
var demoTickets = await GetDemoTicketData(requestData);
|
||||||
foreach (var ticket in demoTickets)
|
foreach (var ticket in demoTickets)
|
||||||
{
|
{
|
||||||
output.Add(new cF4SDTicketSummary()
|
output.Add(new cF4SDTicketSummaryDemo()
|
||||||
{
|
{
|
||||||
Id = ticket.Id,
|
Id = ticket.Id,
|
||||||
Name = ticket.Name,
|
Name = ticket.Name,
|
||||||
@@ -1793,6 +1796,11 @@ namespace C4IT.FASD.Cockpit.Communication
|
|||||||
return new cF4sdStagedSearchResultRelations() { Relations = relations };
|
return new cF4sdStagedSearchResultRelations() { Relations = relations };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Task StopGatheringRelations(Guid id, CancellationToken token)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task DoLocalQuickActionAsync(string ActionPrefix, string ActionNaming)
|
private async Task DoLocalQuickActionAsync(string ActionPrefix, string ActionNaming)
|
||||||
{
|
{
|
||||||
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
||||||
|
|||||||
@@ -308,6 +308,58 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Tickets": [
|
"Tickets": [
|
||||||
|
{
|
||||||
|
"TicketId": "8f3ef61d-6f59-44ee-ae2e-38e7dd9d6f61",
|
||||||
|
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
|
||||||
|
"TileKey": "ServiceRequestsNew",
|
||||||
|
"UseRoleScope": false,
|
||||||
|
"ActivityType": "SPSActivityTypeServiceRequest",
|
||||||
|
"DisplayName": "SRQ00001",
|
||||||
|
"Summary": "Neue Software fuer den Arbeitsplatz bereitstellen",
|
||||||
|
"StatusId": "New",
|
||||||
|
"UserDisplayName": "Busch, Andrea",
|
||||||
|
"UserAccount": "AB014",
|
||||||
|
"UserDomain": "CONTOSO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TicketId": "8f3ef61d-6f59-44ee-ae2e-38e7dd9d6f61",
|
||||||
|
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
|
||||||
|
"TileKey": "ServiceRequestsActive",
|
||||||
|
"UseRoleScope": false,
|
||||||
|
"ActivityType": "SPSActivityTypeServiceRequest",
|
||||||
|
"DisplayName": "SRQ00001",
|
||||||
|
"Summary": "Neue Software fuer den Arbeitsplatz bereitstellen",
|
||||||
|
"StatusId": "InProgress",
|
||||||
|
"UserDisplayName": "Busch, Andrea",
|
||||||
|
"UserAccount": "AB014",
|
||||||
|
"UserDomain": "CONTOSO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TicketId": "8f3ef61d-6f59-44ee-ae2e-38e7dd9d6f61",
|
||||||
|
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
|
||||||
|
"TileKey": "ServiceRequestsCritical",
|
||||||
|
"UseRoleScope": false,
|
||||||
|
"ActivityType": "SPSActivityTypeServiceRequest",
|
||||||
|
"DisplayName": "SRQ00001",
|
||||||
|
"Summary": "Neue Software fuer den Arbeitsplatz bereitstellen",
|
||||||
|
"StatusId": "InProgress",
|
||||||
|
"UserDisplayName": "Busch, Andrea",
|
||||||
|
"UserAccount": "AB014",
|
||||||
|
"UserDomain": "CONTOSO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"TicketId": "8f3ef61d-6f59-44ee-ae2e-38e7dd9d6f61",
|
||||||
|
"UserId": "a2164ecd-791f-482c-bea3-f089f14bec8a",
|
||||||
|
"TileKey": "ServiceRequestsNewInfo",
|
||||||
|
"UseRoleScope": false,
|
||||||
|
"ActivityType": "SPSActivityTypeServiceRequest",
|
||||||
|
"DisplayName": "SRQ00001",
|
||||||
|
"Summary": "Neue Software fuer den Arbeitsplatz bereitstellen",
|
||||||
|
"StatusId": "OnHold",
|
||||||
|
"UserDisplayName": "Busch, Andrea",
|
||||||
|
"UserAccount": "AB014",
|
||||||
|
"UserDomain": "CONTOSO"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"TicketId": "7e852bb9-420b-4caa-b79a-9178d793fc06",
|
"TicketId": "7e852bb9-420b-4caa-b79a-9178d793fc06",
|
||||||
"UserId": "a2c35ad1-7cc7-4b2b-9aa5-d03fdaecd155",
|
"UserId": "a2c35ad1-7cc7-4b2b-9aa5-d03fdaecd155",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using C4IT.FASD.Base;
|
|||||||
|
|
||||||
namespace FasdCockpitCommunicationDemo
|
namespace FasdCockpitCommunicationDemo
|
||||||
{
|
{
|
||||||
public class cF4SDTicketSummary
|
public class cF4SDTicketSummaryDemo
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
@@ -15,7 +15,7 @@ namespace FasdCockpitCommunicationDemo
|
|||||||
public enumTicketStatus Status { get; set; }
|
public enumTicketStatus Status { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class cF4SDTicket : cF4SDTicketSummary
|
public class cF4SDTicketDemo : cF4SDTicketSummaryDemo
|
||||||
{
|
{
|
||||||
public enum enumTicketCreationSource
|
public enum enumTicketCreationSource
|
||||||
{
|
{
|
||||||
@@ -26,7 +26,7 @@ namespace FasdCockpitCommunicationDemo
|
|||||||
F4SD = 3
|
F4SD = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
public class cTicketJournalItem
|
public class cTicketJournalItemDemo
|
||||||
{
|
{
|
||||||
public double CreationDaysSinceNow { get; set; }
|
public double CreationDaysSinceNow { get; set; }
|
||||||
public DateTime CreationDate { get; set; }
|
public DateTime CreationDate { get; set; }
|
||||||
@@ -54,7 +54,7 @@ namespace FasdCockpitCommunicationDemo
|
|||||||
public string SolutionHtml { get; set; }
|
public string SolutionHtml { get; set; }
|
||||||
public Dictionary<string, string> DirectLinks { get; set; }
|
public Dictionary<string, string> DirectLinks { get; set; }
|
||||||
|
|
||||||
public List<cTicketJournalItem> JournalItems { get; set; }
|
public List<cTicketJournalItemDemo> JournalItems { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.2" newVersion="10.0.0.2" />
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.3" newVersion="10.0.0.3" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace C4IT.FASD.Base
|
|||||||
|
|
||||||
public List<cF4SDHealthCardRawData.cHealthCardDetailsTable> DetailsTables { get; set; }
|
public List<cF4SDHealthCardRawData.cHealthCardDetailsTable> DetailsTables { get; set; }
|
||||||
|
|
||||||
public List<cF4SDTicket> Tickets { get; set; } = new List<cF4SDTicket>();
|
public List<cF4SDTicketDemo> Tickets { get; set; } = new List<cF4SDTicketDemo>();
|
||||||
|
|
||||||
public cF4SDHealthCardRawData GetHealthCardData()
|
public cF4SDHealthCardRawData GetHealthCardData()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net472" />
|
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
|
||||||
</packages>
|
</packages>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.2" newVersion="10.0.0.2" />
|
<bindingRedirect oldVersion="0.0.0.0-10.0.0.3" newVersion="10.0.0.3" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
|
|||||||
@@ -4,10 +4,14 @@ using C4IT.FASD.Security;
|
|||||||
using C4IT.Graphics;
|
using C4IT.Graphics;
|
||||||
using C4IT.Logging;
|
using C4IT.Logging;
|
||||||
using C4IT.MultiLanguage;
|
using C4IT.MultiLanguage;
|
||||||
|
using C4IT.XML;
|
||||||
|
using F4SD.ActionConnector.Bus;
|
||||||
|
using F4SD.ActionConnector.Models;
|
||||||
using FasdDesktopUi.Basics;
|
using FasdDesktopUi.Basics;
|
||||||
using FasdDesktopUi.Basics.Helper;
|
using FasdDesktopUi.Basics.Helper;
|
||||||
using FasdDesktopUi.Basics.Models;
|
using FasdDesktopUi.Basics.Models;
|
||||||
using FasdDesktopUi.Basics.Services.Models;
|
using FasdDesktopUi.Basics.Services.Models;
|
||||||
|
using FasdDesktopUi.Basics.UiActions.NativeActions;
|
||||||
using FasdDesktopUi.Pages.CustomMessageBox;
|
using FasdDesktopUi.Pages.CustomMessageBox;
|
||||||
using FasdDesktopUi.Pages.PhoneSettingsPage;
|
using FasdDesktopUi.Pages.PhoneSettingsPage;
|
||||||
using FasdDesktopUi.Pages.SearchPage;
|
using FasdDesktopUi.Pages.SearchPage;
|
||||||
@@ -46,6 +50,8 @@ namespace FasdDesktopUi
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private ActionBus _actionBus;
|
||||||
|
|
||||||
private async void Application_Startup(object sender, StartupEventArgs e)
|
private async void Application_Startup(object sender, StartupEventArgs e)
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
@@ -127,7 +133,24 @@ namespace FasdDesktopUi
|
|||||||
|
|
||||||
InitializeNotifyIcon();
|
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);
|
await cAppStartUp.StartAsync(e.Args);
|
||||||
notifyIcon.Visible = true;
|
notifyIcon.Visible = true;
|
||||||
@@ -491,7 +514,7 @@ namespace FasdDesktopUi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private async void Application_Exit(object sender, ExitEventArgs e)
|
private async void Application_Exit(object sender, ExitEventArgs e)
|
||||||
{
|
{
|
||||||
@@ -506,13 +529,14 @@ namespace FasdDesktopUi
|
|||||||
closeUserSessionTask = cFasdCockpitCommunicationBase.Instance?.CloseUserSession(cFasdCockpitConfig.SessionId).ConfigureAwait(false);
|
closeUserSessionTask = cFasdCockpitCommunicationBase.Instance?.CloseUserSession(cFasdCockpitConfig.SessionId).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await cFasdCockpitCommunicationBase.Instance?.TerminateAsync();
|
if (cFasdCockpitCommunicationBase.Instance != null)
|
||||||
|
await cFasdCockpitCommunicationBase.Instance?.TerminateAsync();
|
||||||
|
|
||||||
if (notifyIcon != null)
|
if (notifyIcon != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
cConnectionStatusHelper.Instance.IsActive = false;
|
cConnectionStatusHelper.Instance.ApplicationIsExiting = true;
|
||||||
notifyIcon.Visible = false;
|
notifyIcon.Visible = false;
|
||||||
notifyIcon.Dispose();
|
notifyIcon.Dispose();
|
||||||
cAppStartUp.Terminate();
|
cAppStartUp.Terminate();
|
||||||
@@ -544,6 +568,8 @@ namespace FasdDesktopUi
|
|||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
|
_actionBus?.Stop();
|
||||||
|
|
||||||
if (closeUserSessionTask is ConfiguredTaskAwaitable _t)
|
if (closeUserSessionTask is ConfiguredTaskAwaitable _t)
|
||||||
await _t;
|
await _t;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ using C4IT.MultiLanguage;
|
|||||||
using C4IT.F4SD.TAPI;
|
using C4IT.F4SD.TAPI;
|
||||||
|
|
||||||
using static C4IT.Logging.cLogManager;
|
using static C4IT.Logging.cLogManager;
|
||||||
|
using F4SD.Gamification.Services;
|
||||||
|
using F4SD.Gamification;
|
||||||
|
|
||||||
|
|
||||||
namespace FasdDesktopUi
|
namespace FasdDesktopUi
|
||||||
@@ -48,6 +50,9 @@ namespace FasdDesktopUi
|
|||||||
LogMethodBegin(CM);
|
LogMethodBegin(CM);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
GamificationService.Initialize();
|
||||||
|
LevelService.LevelChanged += HandleLevelChanged;
|
||||||
|
|
||||||
#if isDemo
|
#if isDemo
|
||||||
cFasdCockpitCommunicationBase.Instance = new cFasdCockpitCommunicationDemo();
|
cFasdCockpitCommunicationBase.Instance = new cFasdCockpitCommunicationDemo();
|
||||||
#else
|
#else
|
||||||
@@ -91,6 +96,7 @@ namespace FasdDesktopUi
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
||||||
splashScreen?.Hide();
|
splashScreen?.Hide();
|
||||||
LogMethodEnd(CM);
|
LogMethodEnd(CM);
|
||||||
}
|
}
|
||||||
@@ -98,6 +104,20 @@ namespace FasdDesktopUi
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void HandleLevelChanged(object sender, LevelEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.CurrentLevel <= 1 || !cFasdCockpitConfig.Instance.Global.UseGamification)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Dispatcher.CurrentDispatcher.Invoke(async () =>
|
||||||
|
{
|
||||||
|
Pages.LevelUpPage.LevelUpPage levelUpWindow = new Pages.LevelUpPage.LevelUpPage();
|
||||||
|
levelUpWindow.NewLevel = e.CurrentLevel;
|
||||||
|
levelUpWindow.LevelTitle = e.LevelTitle;
|
||||||
|
levelUpWindow.Show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static bool ProcessCommandLine(string[] Args)
|
public static bool ProcessCommandLine(string[] Args)
|
||||||
{
|
{
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
|
|||||||
27
FasdDesktopUi/Basics/Converter/LanguageCultureConverter.cs
Normal file
27
FasdDesktopUi/Basics/Converter/LanguageCultureConverter.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Markup;
|
||||||
|
|
||||||
|
namespace FasdDesktopUi.Basics.Converter
|
||||||
|
{
|
||||||
|
[ValueConversion(typeof(string), typeof(XmlLanguage))]
|
||||||
|
internal class LanguageCultureConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (!(value is string tag))
|
||||||
|
return Binding.DoNothing;
|
||||||
|
|
||||||
|
return XmlLanguage.GetLanguage(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (!(value is XmlLanguage lang))
|
||||||
|
return Binding.DoNothing;
|
||||||
|
|
||||||
|
return lang.IetfLanguageTag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,7 +31,7 @@ namespace FasdDesktopUi.Basics
|
|||||||
var http = GetHttpHelper(false);
|
var http = GetHttpHelper(false);
|
||||||
|
|
||||||
var searchResultInfoClass = cF4sdIdentityEntry.GetFromSearchResult(enumF4sdSearchResultClass.Computer);
|
var searchResultInfoClass = cF4sdIdentityEntry.GetFromSearchResult(enumF4sdSearchResultClass.Computer);
|
||||||
var parameter = new cF4SDServerQuickActionParameters() { Action = ServerAction.Action, Category = ServerAction.Category, ParamaterType = ServerAction.ParameterType, Identities = dataProvider.Identities, AdjustableParameter = ParameterDictionary };
|
var parameter = new cF4SDServerQuickActionParameters() { Action = ServerAction.Action, Category = ServerAction.Category, ParameterType = ServerAction.ParameterType, Identities = dataProvider.Identities, AdjustableParameter = ParameterDictionary };
|
||||||
var payload = JsonConvert.SerializeObject(parameter);
|
var payload = JsonConvert.SerializeObject(parameter);
|
||||||
|
|
||||||
var result = await http.PostJsonAsync("api/QuickAction/Run", payload, 15000, CancellationToken.None);
|
var result = await http.PostJsonAsync("api/QuickAction/Run", payload, 15000, CancellationToken.None);
|
||||||
|
|||||||
126
FasdDesktopUi/Basics/Helper/ActionDisplayTypeInspector.cs
Normal file
126
FasdDesktopUi/Basics/Helper/ActionDisplayTypeInspector.cs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
using C4IT.FASD.Base;
|
||||||
|
using FasdDesktopUi.Basics.Enums;
|
||||||
|
using FasdDesktopUi.Basics.Models;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
|
namespace FasdDesktopUi.Basics.Helper
|
||||||
|
{
|
||||||
|
internal static class ActionDisplayTypeInspector
|
||||||
|
{
|
||||||
|
internal static enumActionDisplayType GetDisplayType(cFasdBaseConfigMenuItem menuDataDefinition, cNamedParameterList namedParameterEntries, IEnumerable<enumFasdInformationClass> availableInformationClasses)
|
||||||
|
{
|
||||||
|
if (menuDataDefinition.IsHidden)
|
||||||
|
return enumActionDisplayType.hidden;
|
||||||
|
else if (IsEnabled(menuDataDefinition, namedParameterEntries, availableInformationClasses))
|
||||||
|
return enumActionDisplayType.enabled;
|
||||||
|
else
|
||||||
|
return enumActionDisplayType.disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsEnabled(cFasdBaseConfigMenuItem menuDataDefinition, cNamedParameterList namedParameterEntries, IEnumerable<enumFasdInformationClass> availableInformationClasses)
|
||||||
|
{
|
||||||
|
if (!HasRequiredInformationClasses(menuDataDefinition, availableInformationClasses))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (menuDataDefinition is cFasdQuickAction quickActionDefinition && !IsQuickActionEnabled(quickActionDefinition, namedParameterEntries))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsQuickActionEnabled(cFasdQuickAction quickActionDefinition, cNamedParameterList namedParameterEntries)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(quickActionDefinition.CheckFilePath) && !FileExists(quickActionDefinition.CheckFilePath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(quickActionDefinition.CheckRegistryEntry) && !RegistryEntryExists(quickActionDefinition.CheckRegistryEntry))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (namedParameterEntries is null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
cNamedParameterEntryBase namedParameterValue = null;
|
||||||
|
if (!string.IsNullOrEmpty(quickActionDefinition.CheckNamedParameter) && !namedParameterEntries.TryGetValue(quickActionDefinition.CheckNamedParameter, out namedParameterValue))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (namedParameterValue != null && quickActionDefinition.CheckNamedParameterValues != null && !quickActionDefinition.CheckNamedParameterValues.Contains(namedParameterValue.GetValue()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool HasRequiredInformationClasses(cFasdBaseConfigMenuItem definition, IEnumerable<enumFasdInformationClass> availableInformationClasses)
|
||||||
|
{
|
||||||
|
if (definition?.InformationClasses is null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (definition.InformationClasses.Count == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (definition.InformationClasses.Any(i => !availableInformationClasses.Contains(i)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool FileExists(string path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var specialFolders = Enum.GetValues(typeof(Environment.SpecialFolder)).Cast<Environment.SpecialFolder>();
|
||||||
|
|
||||||
|
foreach (var specialFolder in specialFolders)
|
||||||
|
{
|
||||||
|
string specialFolderName = $"%{specialFolder}%";
|
||||||
|
string specialFolderPath = Environment.GetFolderPath(specialFolder);
|
||||||
|
path = path.Replace(specialFolderName, specialFolderPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
path = Environment.ExpandEnvironmentVariables(path);
|
||||||
|
return File.Exists(path);
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool RegistryEntryExists(string entry)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(entry))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
string rootPath = entry.Split('\\')[0];
|
||||||
|
entry = entry.Replace(rootPath, "").Remove(0, 1);
|
||||||
|
|
||||||
|
switch (rootPath)
|
||||||
|
{
|
||||||
|
case "HKEY_LOCAL_MACHINE":
|
||||||
|
case "HKLM":
|
||||||
|
return Registry.LocalMachine.OpenSubKey(entry) != null;
|
||||||
|
case "HKEY_CURRENT_USER":
|
||||||
|
case "HKCU":
|
||||||
|
return Registry.CurrentUser.OpenSubKey(entry) != null;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
|
||||||
|
|
||||||
using C4IT.Configuration;
|
using C4IT.Configuration;
|
||||||
using C4IT.F4SD.DisplayFormatting;
|
using C4IT.F4SD.DisplayFormatting;
|
||||||
@@ -27,7 +26,6 @@ using FasdDesktopUi.Pages.SlimPage.Models;
|
|||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Newtonsoft.Json.Serialization;
|
|
||||||
|
|
||||||
using static C4IT.FASD.Base.cF4SDHealthCardRawData;
|
using static C4IT.FASD.Base.cF4SDHealthCardRawData;
|
||||||
using static C4IT.Logging.cLogManager;
|
using static C4IT.Logging.cLogManager;
|
||||||
@@ -80,7 +78,7 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
{
|
{
|
||||||
this.dataProvider = dataProvider;
|
this.dataProvider = dataProvider;
|
||||||
_menuDataProvider = new MenuItemDataProvider(dataProvider);
|
_menuDataProvider = new MenuItemDataProvider(dataProvider);
|
||||||
cUtility.RawValueFormatter.SetDefaultCulture(new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
|
cUtility.RawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
|
||||||
cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
|
cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
|
||||||
|
|
||||||
HistoryData = new cHealthCardHistoryDataHelper(this);
|
HistoryData = new cHealthCardHistoryDataHelper(this);
|
||||||
@@ -149,7 +147,7 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
if (informationClasses is null)
|
if (informationClasses is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
foreach (var healthCard in cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.HealthCards.Values)
|
foreach (var healthCard in cF4SDCockpitXmlConfig.Instance?.HealthCardConfig?.HealthCards?.Values)
|
||||||
{
|
{
|
||||||
bool found = true;
|
bool found = true;
|
||||||
|
|
||||||
@@ -250,7 +248,7 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
{
|
{
|
||||||
List<object> output = new List<object>();
|
List<object> output = new List<object>();
|
||||||
|
|
||||||
if (healthCardColumn?.Values == null)
|
if (healthCardColumn?.Values == null || startingIndex < 0)
|
||||||
return output;
|
return output;
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -453,13 +451,9 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
|
|
||||||
var stateValue = GetStateValueAt(stateDefinition.DatabaseInfo, dayIndex, isStatic);
|
var stateValue = GetStateValueAt(stateDefinition.DatabaseInfo, dayIndex, isStatic);
|
||||||
|
|
||||||
enumHighlightColor? tempColor = null;
|
enumHighlightColor? tempColor = GetHighlightColor(stateValue, stateDefinition, dayIndex, isStatic);
|
||||||
if (stateValue != null)
|
if (tempColor == enumHighlightColor.none && stateValue != null)
|
||||||
{
|
tempColor = enumHighlightColor.green;
|
||||||
tempColor = GetHighlightColor(stateValue, stateDefinition, dayIndex, isStatic);
|
|
||||||
if (tempColor == enumHighlightColor.none && stateValue != null)
|
|
||||||
tempColor = enumHighlightColor.green;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output == null)
|
if (output == null)
|
||||||
output = tempColor;
|
output = tempColor;
|
||||||
@@ -492,7 +486,7 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FormattingOptions options = new FormattingOptions() { ReferenceDate = DateTime.UtcNow.Date.AddDays(columnIndex), TimeZone = TimeZoneInfo.Local };
|
FormattingOptions options = new FormattingOptions() { ReferenceDate = DateTime.UtcNow.Date.AddDays(-columnIndex), TimeZone = TimeZoneInfo.Local };
|
||||||
var _c = cUtility.RawValueFormatter.GetDisplayValue(value, Requirements.valueState.DisplayType, options);
|
var _c = cUtility.RawValueFormatter.GetDisplayValue(value, Requirements.valueState.DisplayType, options);
|
||||||
if (!string.IsNullOrWhiteSpace(_c))
|
if (!string.IsNullOrWhiteSpace(_c))
|
||||||
cellContent.Content = _c;
|
cellContent.Content = _c;
|
||||||
@@ -689,11 +683,19 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
{
|
{
|
||||||
if (NamedParameters == null)
|
if (NamedParameters == null)
|
||||||
return false;
|
return false;
|
||||||
|
var _invert = false;
|
||||||
|
if (namedParameter.StartsWith("!"))
|
||||||
|
{
|
||||||
|
_invert = true;
|
||||||
|
namedParameter = namedParameter.Remove(0, 1);
|
||||||
|
}
|
||||||
if (!NamedParameters.TryGetValue(namedParameter, out var entry))
|
if (!NamedParameters.TryGetValue(namedParameter, out var entry))
|
||||||
return false;
|
return _invert;
|
||||||
|
|
||||||
var entryValue = entry.GetValue();
|
var entryValue = entry.GetValue();
|
||||||
cConfigRegistryHelper.ReadFromStringBoolean(entryValue, out var result);
|
cConfigRegistryHelper.ReadFromStringBoolean(entryValue, out var result);
|
||||||
|
if (_invert)
|
||||||
|
result = !result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1113,11 +1115,14 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const string defaultCopyTemplateParameterName = "Copy_default";
|
const string defaultCopyTemplateParameterName = "Copy_default";
|
||||||
if (!dataProvider.NamedParameterEntries.ContainsKey(defaultCopyTemplateParameterName))
|
if (!dataProvider.NamedParameterEntries.ContainsKey(defaultCopyTemplateParameterName))
|
||||||
{
|
{
|
||||||
|
|
||||||
string defaultCopyTemplate = cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate.Name;
|
string defaultCopyTemplate = cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate.Name;
|
||||||
dataProvider.NamedParameterEntries.Add(defaultCopyTemplateParameterName, new cNamedParameterEntryCopyTemplate(dataProvider, defaultCopyTemplate));
|
|
||||||
|
dataProvider.NamedParameterEntries.Add(defaultCopyTemplateParameterName, new cNamedParameterEntryCopyTemplate(dataProvider, SelectedHealthCard.DefaultCopyTemplate != null ? SelectedHealthCard.DefaultCopyTemplate : defaultCopyTemplate));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var copyTemplate in cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.CopyTemplates)
|
foreach (var copyTemplate in cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.CopyTemplates)
|
||||||
@@ -1202,8 +1207,8 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
var historySectionValueColumns = new List<DetailsPageDataHistoryColumnModel>(valueColumnCount);
|
var historySectionValueColumns = new List<DetailsPageDataHistoryColumnModel>(valueColumnCount);
|
||||||
for (int i = 0; i < valueColumnCount; i++)
|
for (int i = 0; i < valueColumnCount; i++)
|
||||||
{
|
{
|
||||||
CultureInfo culture = new CultureInfo(cMultiLanguageSupport.CurrentLanguage);
|
CultureInfo culture = cFasdCockpitConfig.Instance.SelectedCulture;
|
||||||
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 valueColumnHeader = i != 0 ? DateTime.Today.AddDays(-i).ToString($"ddd. {cUtility.GetShortDatePattern()}") : cMultiLanguageSupport.GetItem("Global.Date.Today");
|
||||||
var summaryStatusColor = parent.GetSummaryStatusColor(stateCategoryDefinition.States, false, i);
|
var summaryStatusColor = parent.GetSummaryStatusColor(stateCategoryDefinition.States, false, i);
|
||||||
var valueColumn = new DetailsPageDataHistoryColumnModel() { ColumnValues = new List<cDataHistoryValueModel>(), Content = valueColumnHeader, HighlightColor = summaryStatusColor ?? enumHighlightColor.none };
|
var valueColumn = new DetailsPageDataHistoryColumnModel() { ColumnValues = new List<cDataHistoryValueModel>(), Content = valueColumnHeader, HighlightColor = summaryStatusColor ?? enumHighlightColor.none };
|
||||||
historySectionValueColumns.Add(valueColumn);
|
historySectionValueColumns.Add(valueColumn);
|
||||||
@@ -2165,6 +2170,7 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
|
|
||||||
bool isDataIncomplete = true;
|
bool isDataIncomplete = true;
|
||||||
await LoadingRawDataCriticalSection.EnterAsync();
|
await LoadingRawDataCriticalSection.EnterAsync();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (HealthCardRawData)
|
lock (HealthCardRawData)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using C4IT.FASD.Base;
|
using C4IT.FASD.Base;
|
||||||
using FasdDesktopUi.Basics.Enums;
|
using FasdDesktopUi.Basics.Enums;
|
||||||
using FasdDesktopUi.Basics.Models;
|
using FasdDesktopUi.Basics.Models;
|
||||||
|
using FasdDesktopUi.Basics.Services.SupportCase.Processors;
|
||||||
using FasdDesktopUi.Basics.UiActions;
|
using FasdDesktopUi.Basics.UiActions;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using System;
|
using System;
|
||||||
@@ -15,7 +16,6 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
internal class MenuItemDataProvider
|
internal class MenuItemDataProvider
|
||||||
{
|
{
|
||||||
private readonly cSupportCaseDataProvider _dataProvider;
|
private readonly cSupportCaseDataProvider _dataProvider;
|
||||||
|
|
||||||
private const int defaultPinnedActionCount = 3; //search, notepad, copyTicketInformation
|
private const int defaultPinnedActionCount = 3; //search, notepad, copyTicketInformation
|
||||||
|
|
||||||
public MenuItemDataProvider(cSupportCaseDataProvider dataProvider)
|
public MenuItemDataProvider(cSupportCaseDataProvider dataProvider)
|
||||||
@@ -58,7 +58,7 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
return menuItemData;
|
return menuItemData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private cMenuDataBase GetMenuItem(cFasdBaseConfigMenuItem menuItemConfig)
|
internal cMenuDataBase GetMenuItem(cFasdBaseConfigMenuItem menuItemConfig)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -81,7 +81,7 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
|
|
||||||
if (menuItem != null)
|
if (menuItem != null)
|
||||||
{
|
{
|
||||||
if (!cHealthCardDataHelper.IsUiVisible(menuItemConfig, _dataProvider.NamedParameterEntries))
|
if (_dataProvider != null && !cHealthCardDataHelper.IsUiVisible(menuItemConfig, _dataProvider.NamedParameterEntries))
|
||||||
menuItem.SetUiActionDisplayType(enumActionDisplayType.hidden);
|
menuItem.SetUiActionDisplayType(enumActionDisplayType.hidden);
|
||||||
}
|
}
|
||||||
return menuItem;
|
return menuItem;
|
||||||
@@ -129,7 +129,7 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool HasAllRequirements(cFasdQuickAction quickAction)
|
internal bool HasAllRequirements(cFasdQuickAction quickAction)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -137,9 +137,14 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// if CheckNamedParamter the value of NamedParameter is set and if required equals one of the necessary values
|
// if CheckNamedParamter the value of NamedParameter is set and if required equals one of the necessary values
|
||||||
bool hasRequiredNamedParameter = quickAction.CheckNamedParameter is null
|
bool hasRequiredNamedParameter = true;
|
||||||
|| (_dataProvider.NamedParameterEntries.TryGetValue(quickAction.CheckNamedParameter, out var namedParameterEntry)
|
|
||||||
&& (quickAction.CheckNamedParameterValues is null || quickAction.CheckNamedParameterValues.Count == 0 || quickAction.CheckNamedParameterValues.Contains(namedParameterEntry.GetValue())));
|
if (_dataProvider != null)
|
||||||
|
{
|
||||||
|
hasRequiredNamedParameter = quickAction.CheckNamedParameter is null
|
||||||
|
|| (_dataProvider.NamedParameterEntries.TryGetValue(quickAction.CheckNamedParameter, out var namedParameterEntry)
|
||||||
|
&& (quickAction.CheckNamedParameterValues is null || quickAction.CheckNamedParameterValues.Count == 0 || quickAction.CheckNamedParameterValues.Contains(namedParameterEntry.GetValue())));
|
||||||
|
}
|
||||||
|
|
||||||
if (!hasRequiredNamedParameter)
|
if (!hasRequiredNamedParameter)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,18 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Documents;
|
using System.Windows.Documents;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Shapes;
|
|
||||||
using static C4IT.Logging.cLogManager;
|
using static C4IT.Logging.cLogManager;
|
||||||
using static System.Net.Mime.MediaTypeNames;
|
|
||||||
|
|
||||||
namespace FasdDesktopUi.Basics.Helper
|
namespace FasdDesktopUi.Basics.Helper
|
||||||
{
|
{
|
||||||
@@ -20,7 +13,7 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
{
|
{
|
||||||
#region Unicode
|
#region Unicode
|
||||||
|
|
||||||
public static void TraverseBlockAsUnicode(BlockCollection blocks, StringBuilder stringBuilder, bool isBlockFromList = false)
|
public static void TraverseBlockAsUnicode(BlockCollection blocks, StringBuilder stringBuilder)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -54,15 +47,11 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
|
|
||||||
private static void TraverseParagraphAsUnicode(Paragraph paragraph, StringBuilder stringBuilder)
|
private static void TraverseParagraphAsUnicode(Paragraph paragraph, StringBuilder stringBuilder)
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (var inline in paragraph.Inlines)
|
foreach (Run run in paragraph.Inlines.OfType<Run>())
|
||||||
{
|
{
|
||||||
if (inline is Run run)
|
stringBuilder.Append(run.Text);
|
||||||
{
|
|
||||||
stringBuilder.Append(run.Text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
@@ -73,32 +62,24 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
|
|
||||||
private static void TraverseListAsUnicode(List list, StringBuilder stringBuilder)
|
private static void TraverseListAsUnicode(List list, StringBuilder stringBuilder)
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
if (list.MarkerStyle == TextMarkerStyle.Decimal)
|
if (list.MarkerStyle == TextMarkerStyle.Decimal)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int i = 0; i < list.ListItems.Count; i++)
|
for (int i = 0; i < list.ListItems.Count; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
stringBuilder.Append(i + 1 + ". ");
|
stringBuilder.Append(i + 1 + ". ");
|
||||||
TraverseBlockAsUnicode(list.ListItems.ElementAt(i).Blocks, stringBuilder, true);
|
TraverseBlockAsUnicode(list.ListItems.ElementAt(i).Blocks, stringBuilder);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var item in list.ListItems)
|
foreach (var item in list.ListItems)
|
||||||
{
|
{
|
||||||
|
|
||||||
stringBuilder.Append("- ");
|
stringBuilder.Append("- ");
|
||||||
TraverseBlockAsUnicode(item.Blocks, stringBuilder, true);
|
TraverseBlockAsUnicode(item.Blocks, stringBuilder);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
@@ -108,18 +89,14 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
|
|
||||||
private static void TraverseImageAsUnicode(System.Windows.Controls.Image image, StringBuilder stringBuilder)
|
private static void TraverseImageAsUnicode(System.Windows.Controls.Image image, StringBuilder stringBuilder)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
stringBuilder.Append("[Image]");
|
stringBuilder.Append($"[Image:\"{image.Name}\"]");
|
||||||
}
|
}
|
||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
LogException(E);
|
LogException(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -151,12 +128,7 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
else if (block is BlockUIContainer container)
|
else if (block is BlockUIContainer container)
|
||||||
{
|
{
|
||||||
if (container.Child is System.Windows.Controls.Image image)
|
if (container.Child is System.Windows.Controls.Image image)
|
||||||
{
|
|
||||||
|
|
||||||
TraverseImageAsHtml(image, stringBuilder);
|
TraverseImageAsHtml(image, stringBuilder);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +195,6 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
byte[] arr;
|
byte[] arr;
|
||||||
using (MemoryStream ms = new MemoryStream())
|
using (MemoryStream ms = new MemoryStream())
|
||||||
{
|
{
|
||||||
@@ -242,7 +213,6 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
{
|
{
|
||||||
LogException(E);
|
LogException(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void TraverseRunAsHtml(Run run, StringBuilder stringBuilder)
|
public static void TraverseRunAsHtml(Run run, StringBuilder stringBuilder)
|
||||||
|
|||||||
@@ -1,36 +1,39 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using C4IT.FASD.Base;
|
using C4IT.FASD.Base;
|
||||||
|
using C4IT.FASD.Cockpit.Communication;
|
||||||
using C4IT.Logging;
|
using C4IT.Logging;
|
||||||
|
|
||||||
using FasdDesktopUi.Basics;
|
using FasdDesktopUi.Basics;
|
||||||
|
|
||||||
using static C4IT.Logging.cLogManager;
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
namespace FasdDesktopUi.Basics.Helper
|
namespace FasdDesktopUi.Basics.Helper
|
||||||
{
|
{
|
||||||
internal static class TicketDeepLinkHelper
|
internal static class TicketExternalLinkHelper
|
||||||
{
|
{
|
||||||
internal static bool TryOpenTicketRelationExternally(cF4sdApiSearchResultRelation relation)
|
private const string DefaultTicketActivityType = "SPSActivityTypeTicket";
|
||||||
|
|
||||||
|
internal static async Task<bool> TryOpenFinalizedTicketExternallyAsync(Guid ticketId, enumTicketExternalOpenMode mode)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (relation == null || relation.Type != enumF4sdSearchResultClass.Ticket)
|
if (ticketId == Guid.Empty || mode == enumTicketExternalOpenMode.None)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var ticketConfig = cFasdCockpitConfig.Instance?.Global?.TicketConfiguration;
|
var linkResult = await cFasdCockpitCommunicationBase.Instance.GetTicketExternalLinkAsync(ticketId, mode);
|
||||||
if (ticketConfig == null)
|
if (linkResult?.Success != true ||
|
||||||
|
!Uri.TryCreate(linkResult.Url, UriKind.Absolute, out var ticketUri) ||
|
||||||
|
(ticketUri.Scheme != Uri.UriSchemeHttp && ticketUri.Scheme != Uri.UriSchemeHttps))
|
||||||
|
{
|
||||||
|
LogEntry($"Could not resolve an external link for ticket '{ticketId:D}'.", LogLevels.Warning);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var activityType = GetActivityType(relation);
|
new cBrowsers().Start("default", ticketUri.AbsoluteUri);
|
||||||
var openExternally = ShouldOpenExternally(ticketConfig, activityType);
|
|
||||||
|
|
||||||
if (!openExternally)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var url = BuildTicketDeepLink(relation.id, activityType);
|
|
||||||
if (string.IsNullOrWhiteSpace(url))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
new cBrowsers().Start("default", url);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -41,102 +44,131 @@ namespace FasdDesktopUi.Basics.Helper
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetActivityType(cF4sdApiSearchResultRelation relation)
|
internal static bool TryOpenTicketRelationExternally(cF4sdApiSearchResultRelation relation, bool forceExternal = false)
|
||||||
{
|
{
|
||||||
if (relation?.Infos != null && relation.Infos.TryGetValue("ActivityType", out var activityTypeValue))
|
try
|
||||||
return activityTypeValue;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool ShouldOpenExternally(cF4sdTicketConfig ticketConfig, string activityType)
|
|
||||||
{
|
|
||||||
if (ticketConfig == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (TryGetOverride(ticketConfig.OpenActivitiesExternallyOverrides, activityType, out var overrideValue))
|
|
||||||
return overrideValue;
|
|
||||||
|
|
||||||
return ticketConfig.OpenActivitiesExternally;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool TryGetOverride(IEnumerable<string> overrides, string activityType, out bool value)
|
|
||||||
{
|
|
||||||
value = false;
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(activityType) || overrides == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
foreach (var entry in overrides)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(entry))
|
if (relation == null || relation.Type != enumF4sdSearchResultClass.Ticket)
|
||||||
continue;
|
|
||||||
|
|
||||||
var parts = entry.Split(new[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
if (parts.Length != 2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var typeName = parts[0].Trim();
|
|
||||||
if (!string.Equals(typeName, activityType, StringComparison.OrdinalIgnoreCase))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!TryParseBool(parts[1], out value))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
// check how we should open this ticket (intern, extern or both)
|
||||||
|
var ticketType = GetTicketType(relation);
|
||||||
|
var processing = ShouldOpenExternally(ticketType);
|
||||||
|
|
||||||
|
// check if we have a valid user id in the id list => if not we could open this ticket only extern.
|
||||||
|
var hasUser = HasValidUserIdentity(relation);
|
||||||
|
if (forceExternal || !hasUser)
|
||||||
|
processing = enumTicketProcessing.Extern;
|
||||||
|
|
||||||
|
if (processing == enumTicketProcessing.Intern)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var m42Server = cCockpitConfiguration.Instance?.m42ServerConfiguration?.Server;
|
||||||
|
if (!TryGetTicketLink(relation, m42Server, out var ticketLink))
|
||||||
|
{
|
||||||
|
LogEntry($"Could not resolve an external Matrix42 link for ticket '{relation.DisplayName ?? relation.Name}'.", LogLevels.Warning);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
new cBrowsers().Start("default", ticketLink);
|
||||||
|
|
||||||
|
return processing == enumTicketProcessing.Extern;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogException(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool TryParseBool(string value, out bool result)
|
internal static bool HasValidUserIdentity(cF4sdApiSearchResultRelation relation)
|
||||||
{
|
{
|
||||||
result = false;
|
return relation?.Identities?.Any(identity =>
|
||||||
if (string.IsNullOrWhiteSpace(value))
|
identity.Class == enumFasdInformationClass.User && identity.Id != Guid.Empty) == true;
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (value.Trim().ToLowerInvariant())
|
|
||||||
{
|
|
||||||
case "true":
|
|
||||||
case "1":
|
|
||||||
case "yes":
|
|
||||||
result = true;
|
|
||||||
return true;
|
|
||||||
case "false":
|
|
||||||
case "0":
|
|
||||||
case "no":
|
|
||||||
result = false;
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return bool.TryParse(value, out result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string BuildTicketDeepLink(Guid ticketId, string activityType)
|
internal static bool TryGetTicketLink(cF4sdApiSearchResultRelation relation, string m42Server, out string ticketLink)
|
||||||
{
|
{
|
||||||
if (ticketId == Guid.Empty)
|
ticketLink = null;
|
||||||
return null;
|
if (relation == null || relation.Type != enumF4sdSearchResultClass.Ticket)
|
||||||
|
return false;
|
||||||
|
|
||||||
var server = cCockpitConfiguration.Instance?.m42ServerConfiguration?.Server;
|
if (TryGetConfiguredLink(relation, "TicketLink", out ticketLink) ||
|
||||||
if (string.IsNullOrWhiteSpace(server))
|
TryGetConfiguredLink(relation, "DirectLinkPreview", out ticketLink))
|
||||||
return null;
|
|
||||||
|
|
||||||
var baseUrl = server.TrimEnd('/');
|
|
||||||
if (!baseUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
|
|
||||||
!baseUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
baseUrl = "https://" + baseUrl;
|
return true;
|
||||||
}
|
}
|
||||||
if (!baseUrl.EndsWith("/wm", StringComparison.OrdinalIgnoreCase))
|
|
||||||
baseUrl += "/wm";
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(activityType))
|
if (relation.id == Guid.Empty || string.IsNullOrWhiteSpace(m42Server))
|
||||||
return null;
|
return false;
|
||||||
|
|
||||||
var viewOptionsJson = $"{{\"embedded\":false,\"objectId\":\"{ticketId}\",\"type\":\"{activityType}\",\"viewType\":\"preview\",\"archived\":0}}";
|
var server = m42Server.Trim();
|
||||||
var viewOptionsEncoded = Uri.EscapeDataString(viewOptionsJson);
|
if (!server.Contains("://"))
|
||||||
|
server = $"https://{server}";
|
||||||
|
|
||||||
return $"{baseUrl}/app-ServiceDesk/?view-options={viewOptionsEncoded}";
|
if (!Uri.TryCreate(server, UriKind.Absolute, out var serverUri) ||
|
||||||
|
(serverUri.Scheme != Uri.UriSchemeHttp && serverUri.Scheme != Uri.UriSchemeHttps))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var activityType = GetActivityType(relation);
|
||||||
|
var encodedActivityType = Uri.EscapeDataString(activityType);
|
||||||
|
ticketLink = $"{serverUri.Scheme}://{serverUri.Authority}/wm/app-ServiceDesk/notSet/preview-object/{encodedActivityType}/{relation.id:D}/0/";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryGetConfiguredLink(cF4sdApiSearchResultRelation relation, string key, out string ticketLink)
|
||||||
|
{
|
||||||
|
ticketLink = null;
|
||||||
|
if (relation?.Infos?.TryGetValue(key, out var configuredLink) != true || string.IsNullOrWhiteSpace(configuredLink))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ticketLink = configuredLink;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetActivityType(cF4sdApiSearchResultRelation relation)
|
||||||
|
{
|
||||||
|
if (relation?.Infos?.TryGetValue("ActivityType", out var activityType) == true && !string.IsNullOrWhiteSpace(activityType))
|
||||||
|
return activityType.Trim();
|
||||||
|
|
||||||
|
if (relation?.Infos?.TryGetValue("TicketType", out var ticketTypeValue) == true &&
|
||||||
|
Enum.TryParse(ticketTypeValue, true, out enumTicketType ticketType))
|
||||||
|
{
|
||||||
|
switch (ticketType)
|
||||||
|
{
|
||||||
|
case enumTicketType.Incident:
|
||||||
|
return "SPSActivityTypeIncident";
|
||||||
|
case enumTicketType.ServiceRequest:
|
||||||
|
return "SPSActivityTypeServiceRequest";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefaultTicketActivityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static enumTicketType GetTicketType(cF4sdApiSearchResultRelation relation)
|
||||||
|
{
|
||||||
|
if (relation?.Infos != null && relation.Infos.TryGetValue("TicketType", out var ticketTypeValue))
|
||||||
|
{
|
||||||
|
if (Enum.TryParse<enumTicketType>(ticketTypeValue, true, out var ticketType))
|
||||||
|
return ticketType;
|
||||||
|
}
|
||||||
|
return enumTicketType.Ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static enumTicketProcessing ShouldOpenExternally(enumTicketType ticketType)
|
||||||
|
{
|
||||||
|
var ticketConfig = cFasdCockpitConfig.Instance?.Global?.TicketConfiguration;
|
||||||
|
if (ticketConfig == null)
|
||||||
|
return enumTicketProcessing.Extern;
|
||||||
|
|
||||||
|
if (ticketConfig.TicketProcessing?.TryGetValue(ticketType, out var processing) == true)
|
||||||
|
return processing;
|
||||||
|
|
||||||
|
return ticketConfig.DefaultProcessing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
heartBeat
|
heartBeat
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsActive = true;
|
public enumOnlineStatus ApiConnectionStatus { get; private set; } = enumOnlineStatus.notSpecified;
|
||||||
|
|
||||||
|
public bool ApplicationIsExiting { get; set; } = false;
|
||||||
|
|
||||||
public readonly Version MinServerVersion = new Version("0.0.0.0");
|
public readonly Version MinServerVersion = new Version("0.0.0.0");
|
||||||
|
|
||||||
@@ -64,16 +66,15 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
|
|
||||||
public static cConnectionStatusHelper Instance { get; set; }
|
public static cConnectionStatusHelper Instance { get; set; }
|
||||||
|
|
||||||
public bool IsAuthorizationSupported { get; private set; } = false;
|
private bool IsAuthorizationSupported { get; set; } = false;
|
||||||
private System.Timers.Timer timer;
|
private System.Timers.Timer timer;
|
||||||
|
|
||||||
#region Lock Elements Connecion Status
|
#region Lock Elements Connecion Status
|
||||||
private readonly object connectionStatusCheckLock = new object();
|
private readonly object connectionStatusCheckLock = new object();
|
||||||
private enumCheckRunning IsConnectionStatusCheckRunning = enumCheckRunning.no;
|
private enumCheckRunning IsConnectionStatusCheckRunning = enumCheckRunning.no;
|
||||||
|
private int OnlineCheckCounter = 0;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public enumOnlineStatus ApiConnectionStatus = enumOnlineStatus.notSpecified;
|
|
||||||
|
|
||||||
public cConnectionStatusHelper()
|
public cConnectionStatusHelper()
|
||||||
{
|
{
|
||||||
ApiConnectionStatus = enumOnlineStatus.offline;
|
ApiConnectionStatus = enumOnlineStatus.offline;
|
||||||
@@ -125,44 +126,47 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
return (timerInterval, shortInterval);
|
return (timerInterval, shortInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleConnectionStatus(enumConnectionStatus status, ref int timerInterval, int timerInteralShort)
|
private enumOnlineStatus HandleConnectionStatus(enumConnectionStatus status, ref int timerInterval, int timerInteralShort)
|
||||||
{
|
{
|
||||||
|
var newStatus = ApiConnectionStatus;
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case enumConnectionStatus.unknown:
|
case enumConnectionStatus.unknown:
|
||||||
case enumConnectionStatus.serverNotFound:
|
case enumConnectionStatus.serverNotFound:
|
||||||
if (ApiConnectionStatus != enumOnlineStatus.offline)
|
if (newStatus != enumOnlineStatus.offline)
|
||||||
ApiConnectionStatus = enumOnlineStatus.offline;
|
newStatus = enumOnlineStatus.offline;
|
||||||
timerInterval = timerInteralShort;
|
timerInterval = timerInteralShort;
|
||||||
LogEntry("RunConnectionStatusCheckAsync: Exit due to status 'serverNotFound'");
|
LogEntry("RunConnectionStatusCheckAsync: Exit due to status 'serverNotFound'");
|
||||||
break;
|
break;
|
||||||
case enumConnectionStatus.serverResponseError:
|
case enumConnectionStatus.serverResponseError:
|
||||||
ApiConnectionStatus = enumOnlineStatus.connectionError;
|
newStatus = enumOnlineStatus.connectionError;
|
||||||
timerInterval = timerInteralShort;
|
timerInterval = timerInteralShort;
|
||||||
LogEntry("RunConnectionStatusCheckAsync: Exit due to status 'serverResponseError'");
|
LogEntry("RunConnectionStatusCheckAsync: Exit due to status 'serverResponseError'");
|
||||||
break;
|
break;
|
||||||
case enumConnectionStatus.incompatibleServerVersion:
|
case enumConnectionStatus.incompatibleServerVersion:
|
||||||
LogEntry("RunConnectionStatusCheckAsync: Exit due to status 'incompatibleServerVersion'");
|
LogEntry("RunConnectionStatusCheckAsync: Exit due to status 'incompatibleServerVersion'");
|
||||||
ApiConnectionStatus = enumOnlineStatus.incompatibleServerVersion;
|
newStatus = enumOnlineStatus.incompatibleServerVersion;
|
||||||
break;
|
break;
|
||||||
case enumConnectionStatus.serverStarting:
|
case enumConnectionStatus.serverStarting:
|
||||||
ApiConnectionStatus = enumOnlineStatus.serverStarting;
|
newStatus = enumOnlineStatus.serverStarting;
|
||||||
break;
|
break;
|
||||||
case enumConnectionStatus.serverNotConfigured:
|
case enumConnectionStatus.serverNotConfigured:
|
||||||
ApiConnectionStatus = enumOnlineStatus.serverNotConfigured;
|
newStatus = enumOnlineStatus.serverNotConfigured;
|
||||||
break;
|
break;
|
||||||
case enumConnectionStatus.connected:
|
case enumConnectionStatus.connected:
|
||||||
if (cCockpitConfiguration.Instance == null || cF4SDCockpitXmlConfig.Instance == null)
|
if (cCockpitConfiguration.Instance == null || cF4SDCockpitXmlConfig.Instance == null)
|
||||||
ApiConnectionStatus = enumOnlineStatus.illegalConfig;
|
newStatus = enumOnlineStatus.illegalConfig;
|
||||||
else if (ApiConnectionStatus != enumOnlineStatus.online)
|
else if (ApiConnectionStatus != enumOnlineStatus.online)
|
||||||
ApiConnectionStatus = enumOnlineStatus.online;
|
newStatus = enumOnlineStatus.online;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return newStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RunConnectionStatusCheckAsync(SplashScreenView splashScreen)
|
public async Task RunConnectionStatusCheckAsync(SplashScreenView splashScreen)
|
||||||
{
|
{
|
||||||
if (!IsActive)
|
if (ApplicationIsExiting)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var CM = MethodBase.GetCurrentMethod();
|
var CM = MethodBase.GetCurrentMethod();
|
||||||
@@ -195,7 +199,7 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
cCheckConnectionResult connectionResult = await cFasdCockpitCommunicationBase.Instance.CheckConnection(MinServerVersion);
|
cCheckConnectionResult connectionResult = await cFasdCockpitCommunicationBase.Instance.CheckConnection(MinServerVersion);
|
||||||
IsAuthorizationSupported = connectionResult?.ApiConnectionInfo?.SupportAuthorisation ?? false;
|
IsAuthorizationSupported = connectionResult?.ApiConnectionInfo?.SupportAuthorisation ?? false;
|
||||||
|
|
||||||
HandleConnectionStatus(connectionResult.ConnectionStatus, ref timerInterval, shortTimerInterval);
|
ApiConnectionStatus = HandleConnectionStatus(connectionResult.ConnectionStatus, ref timerInterval, shortTimerInterval);
|
||||||
if (connectionResult.ConnectionStatus != enumConnectionStatus.connected)
|
if (connectionResult.ConnectionStatus != enumConnectionStatus.connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -210,7 +214,12 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
var configTasks = await Task.WhenAll(loadConfigFilesTask, getCockpitConfig);
|
var configTasks = await Task.WhenAll(loadConfigFilesTask, getCockpitConfig);
|
||||||
|
|
||||||
if (configTasks.Any(t => t == false))
|
if (configTasks.Any(t => t == false))
|
||||||
|
{
|
||||||
|
LogEntry("Connection status check wasn't successfull. Could not retrieve all configurations.", LogLevels.Warning);
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||||
|
await RunConnectionStatusCheckAsync(splashScreen);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (cFasdCockpitConfig.Instance?.Global != null && cCockpitConfiguration.Instance?.GlobalConfig != null)
|
if (cFasdCockpitConfig.Instance?.Global != null && cCockpitConfiguration.Instance?.GlobalConfig != null)
|
||||||
{
|
{
|
||||||
cFasdCockpitConfig.Instance.Global.Load(cCockpitConfiguration.Instance.GlobalConfig);
|
cFasdCockpitConfig.Instance.Global.Load(cCockpitConfiguration.Instance.GlobalConfig);
|
||||||
@@ -225,33 +234,34 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
}
|
}
|
||||||
if (IsAuthorizationSupported)
|
if (IsAuthorizationSupported)
|
||||||
{
|
{
|
||||||
if (userInfo is null || DateTime.UtcNow > userInfo.RenewUntil)
|
Dispatcher.CurrentDispatcher.Invoke(() => splashScreen?.SetStatusText(cMultiLanguageSupport.GetItem("StartUp.SplashScreen.AuthenticateUser")));
|
||||||
{
|
ApiConnectionStatus = enumOnlineStatus.unauthorized;
|
||||||
Dispatcher.CurrentDispatcher.Invoke(() => splashScreen?.SetStatusText(cMultiLanguageSupport.GetItem("StartUp.SplashScreen.AuthenticateUser")));
|
const string cockpitUserRole = "Cockpit.User";
|
||||||
ApiConnectionStatus = enumOnlineStatus.unauthorized;
|
|
||||||
const string cockpitUserRole = "Cockpit.User";
|
|
||||||
#if isNewFeature
|
#if isNewFeature
|
||||||
const string cockpitTicketAgentRole = "Cockpit.TicketAgent";
|
const string cockpitTicketAgentRole = "Cockpit.TicketAgent";
|
||||||
#endif
|
#endif
|
||||||
|
if (userInfo is null || DateTime.UtcNow > userInfo.RenewUntil)
|
||||||
|
{
|
||||||
userInfo = await cFasdCockpitCommunicationBase.Instance.WinLogon();
|
userInfo = await cFasdCockpitCommunicationBase.Instance.WinLogon();
|
||||||
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
|
lock (cFasdCockpitCommunicationBase.CockpitUserInfoLock)
|
||||||
{
|
{
|
||||||
cFasdCockpitCommunicationBase.CockpitUserInfo = userInfo;
|
cFasdCockpitCommunicationBase.CockpitUserInfo = userInfo;
|
||||||
}
|
}
|
||||||
if (userInfo?.Roles is null || !userInfo.Roles.Contains(cockpitUserRole))
|
}
|
||||||
{
|
|
||||||
Dispatcher.CurrentDispatcher.Invoke(() => splashScreen?.SetStatusText(cMultiLanguageSupport.GetItem("StartUp.SplashScreen.NoAuthorization")));
|
if (userInfo?.Roles is null || !userInfo.Roles.Contains(cockpitUserRole))
|
||||||
LogEntry($"Cockpit User ({userInfo?.Name} with Id {userInfo?.Id}, has not the required permissions.", LogLevels.Error);
|
{
|
||||||
}
|
Dispatcher.CurrentDispatcher.Invoke(() => splashScreen?.SetStatusText(cMultiLanguageSupport.GetItem("StartUp.SplashScreen.NoAuthorization")));
|
||||||
else
|
LogEntry($"Cockpit User ({userInfo?.Name} with Id {userInfo?.Id}, has not the required permissions.", LogLevels.Error);
|
||||||
{
|
}
|
||||||
await Task.Run(async () => await cFasdCockpitConfig.Instance.InstantiateAnalyticsAsync(cFasdCockpitConfig.SessionId));
|
else
|
||||||
ApiConnectionStatus = enumOnlineStatus.online;
|
{
|
||||||
|
await Task.Run(async () => await cFasdCockpitConfig.Instance.InstantiateAnalyticsAsync(cFasdCockpitConfig.SessionId));
|
||||||
|
ApiConnectionStatus = enumOnlineStatus.online;
|
||||||
#if isNewFeature
|
#if isNewFeature
|
||||||
if (userInfo.Roles.Contains(cockpitTicketAgentRole))
|
if (userInfo.Roles.Contains(cockpitTicketAgentRole))
|
||||||
cCockpitConfiguration.Instance.ticketSupport.EditTicket = true;
|
cCockpitConfiguration.Instance.ticketSupport.EditTicket = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -280,9 +290,9 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (App.M42OptionMenuItem != null)
|
if (App.M42OptionMenuItem != null)
|
||||||
App.Current.MainWindow.Dispatcher.Invoke(() =>
|
Dispatcher.CurrentDispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
App.M42OptionMenuItem.Enabled = userInfo != null;
|
App.M42OptionMenuItem.Enabled = userInfo != null;
|
||||||
});
|
});
|
||||||
|
|
||||||
// check, if the are logons needed
|
// check, if the are logons needed
|
||||||
@@ -291,6 +301,7 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
await cFasdCockpitConfig.Instance.CheckServerQuickActionAvailabilityAsync();
|
await cFasdCockpitConfig.Instance.CheckServerQuickActionAvailabilityAsync();
|
||||||
await cFasdCockpitCommunicationBase.Instance.InitializeAfterOnlineAsync();
|
await cFasdCockpitCommunicationBase.Instance.InitializeAfterOnlineAsync();
|
||||||
cFasdCockpitConfig.Instance.OnUiSettingsChanged();
|
cFasdCockpitConfig.Instance.OnUiSettingsChanged();
|
||||||
|
await Task.Run(async () => await cFasdCockpitConfig.Instance.InstantiateAnalyticsAsync(cFasdCockpitConfig.SessionId));
|
||||||
}
|
}
|
||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
@@ -312,7 +323,7 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
LogException(E);
|
LogException(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsActive)
|
if (!ApplicationIsExiting)
|
||||||
{
|
{
|
||||||
if (ApiConnectionStatus == enumOnlineStatus.online)
|
if (ApiConnectionStatus == enumOnlineStatus.online)
|
||||||
NotifyerSupport.SetNotifyIcon("Default", null, NotifyerSupport.enumIconAlignment.BottomRight);
|
NotifyerSupport.SetNotifyIcon("Default", null, NotifyerSupport.enumIconAlignment.BottomRight);
|
||||||
@@ -334,6 +345,7 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
OnlineCheckCounter++;
|
||||||
LogMethodEnd(CM);
|
LogMethodEnd(CM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
175
FasdDesktopUi/Basics/Models/DTOs/MenuDataBaseDto.cs
Normal file
175
FasdDesktopUi/Basics/Models/DTOs/MenuDataBaseDto.cs
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
using C4IT.FASD.Base;
|
||||||
|
using F4SD_AdaptableIcon;
|
||||||
|
using F4SD_AdaptableIcon.Enums;
|
||||||
|
using FasdDesktopUi.Basics.Converter;
|
||||||
|
using FasdDesktopUi.Basics.UiActions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
namespace FasdDesktopUi.Basics.Models.DTOs
|
||||||
|
{
|
||||||
|
// __ __ ____ ____
|
||||||
|
// | |__| || || \
|
||||||
|
// | | | | | | | o )
|
||||||
|
// | | | | | | | _/
|
||||||
|
// | ` ' | | | | |
|
||||||
|
// \ / | | | |
|
||||||
|
// \_/\_/ |____||__|
|
||||||
|
|
||||||
|
// the following classes are work in Progress and shouldn't been used
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
internal readonly struct IconInfo
|
||||||
|
{
|
||||||
|
public IconData? Overlay { get; }
|
||||||
|
public double IconScale { get; }
|
||||||
|
public bool IsInactive { get; }
|
||||||
|
public string Description { get; }
|
||||||
|
|
||||||
|
public IconInfo(bool isInactive = default, string description = null, IconData? overlay = null, double iconScale = 1.0)
|
||||||
|
{
|
||||||
|
Overlay = overlay;
|
||||||
|
IsInactive = isInactive;
|
||||||
|
Description = description;
|
||||||
|
IconScale = iconScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
internal abstract class MenuDataBaseDto
|
||||||
|
{
|
||||||
|
private readonly IconData _icon;
|
||||||
|
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string SubTitle { get; set; }
|
||||||
|
public cUiActionBase Action { get; set; }
|
||||||
|
public IconInfo IconInformation { get; set; }
|
||||||
|
public int PositoinIndex { get; set; }
|
||||||
|
|
||||||
|
protected MenuDataBaseDto() { }
|
||||||
|
|
||||||
|
protected MenuDataBaseDto(cFasdBaseConfigMenuItem menuItemDefinition)
|
||||||
|
{
|
||||||
|
_icon = IconDataConverter.Convert(menuItemDefinition.Icon);
|
||||||
|
Title = menuItemDefinition.Names.GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal virtual IconData GetIcon() => _icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
internal sealed class ContainerMenuDataDto : MenuDataBaseDto
|
||||||
|
{
|
||||||
|
public IList<MenuDataBaseDto> SubMenuData { get; set; } = new List<MenuDataBaseDto>();
|
||||||
|
|
||||||
|
public ContainerMenuDataDto(cFasdMenuSection sectionDefintion) : base(sectionDefintion)
|
||||||
|
{
|
||||||
|
Action = new cSubMenuAction(true); // todo rework subMenuAction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
internal sealed class LoadingMenuDataDto : MenuDataBaseDto
|
||||||
|
{
|
||||||
|
private readonly IconData _icon = new IconData(enumInternGif.loadingSpinner);
|
||||||
|
|
||||||
|
public LoadingMenuDataDto(string loadingText)
|
||||||
|
{
|
||||||
|
Title = loadingText;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override IconData GetIcon() => _icon;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
internal sealed class SearchResultMenuDataDto : MenuDataBaseDto
|
||||||
|
{
|
||||||
|
private readonly cFasdApiSearchResultEntry _searchResultEntry;
|
||||||
|
public enumF4sdSearchResultClass Type { get => _searchResultEntry.Type; }
|
||||||
|
|
||||||
|
public SearchResultMenuDataDto(cFasdApiSearchResultEntry searchResultEntry)
|
||||||
|
{
|
||||||
|
_searchResultEntry = searchResultEntry;
|
||||||
|
//Action = new cUiProcessSearchRelationAction()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override IconData GetIcon()
|
||||||
|
{
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case enumF4sdSearchResultClass.Computer:
|
||||||
|
return new IconData(enumInternIcons.misc_computer);
|
||||||
|
case enumF4sdSearchResultClass.User:
|
||||||
|
return new IconData(enumInternIcons.misc_user);
|
||||||
|
case enumF4sdSearchResultClass.Phone:
|
||||||
|
return new IconData(MaterialIcons.MaterialIconType.ic_phone);
|
||||||
|
case enumF4sdSearchResultClass.Ticket:
|
||||||
|
break;
|
||||||
|
case enumF4sdSearchResultClass.VirtualSession:
|
||||||
|
break;
|
||||||
|
case enumF4sdSearchResultClass.MobileDevice:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
internal sealed class SearchRelationMenuDataDto : MenuDataBaseDto
|
||||||
|
{
|
||||||
|
private readonly cF4sdApiSearchResultRelation _searchRelation;
|
||||||
|
public enumF4sdSearchResultClass Type { get => _searchRelation.Type; }
|
||||||
|
public DateTime LastUsed { get; private set; }
|
||||||
|
public double UsingFactor { get; private set; }
|
||||||
|
public Dictionary<string, string> AdditionalInfos { get; private set; } // todo check
|
||||||
|
|
||||||
|
public bool IsUsedForCaseEnrichtment { get; set; } // todo check
|
||||||
|
|
||||||
|
public string TrailingText { get; set; }
|
||||||
|
|
||||||
|
public SearchRelationMenuDataDto(cF4sdApiSearchResultRelation searchRelation)
|
||||||
|
{
|
||||||
|
_searchRelation = searchRelation;
|
||||||
|
//Action = new cUiProcessSearchRelationAction()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override IconData GetIcon()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
internal sealed class QuickActionMenuDataDto : MenuDataBaseDto
|
||||||
|
{
|
||||||
|
public QuickActionMenuDataDto(cFasdQuickAction quickActionDefinition) : base(quickActionDefinition)
|
||||||
|
{
|
||||||
|
Action = cUiActionBase.GetUiAction(quickActionDefinition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
internal sealed class QuickTipMenuDataDto : MenuDataBaseDto
|
||||||
|
{
|
||||||
|
public QuickTipMenuDataDto(cFasdQuickTip quickTipDefinition) : base(quickTipDefinition)
|
||||||
|
{
|
||||||
|
Title = quickTipDefinition.Names.GetValue();
|
||||||
|
Action = new cUiQuickTipAction(quickTipDefinition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
internal sealed class CopyTemplateMenuDataDto : MenuDataBaseDto
|
||||||
|
{
|
||||||
|
public CopyTemplateMenuDataDto(cCopyTemplate copyActionDefintion) : base(copyActionDefintion)
|
||||||
|
{
|
||||||
|
Action = new cUiCopyAction(copyActionDefintion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -119,6 +119,9 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (actionSteps is null)
|
||||||
|
return;
|
||||||
|
|
||||||
foreach (var step in actionSteps)
|
foreach (var step in actionSteps)
|
||||||
{
|
{
|
||||||
if (step.StepType.Equals(type) && step.QuickActionName.Equals(quickActionName))
|
if (step.StepType.Equals(type) && step.QuickActionName.Equals(quickActionName))
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
using C4IT.FASD.Base;
|
using C4IT.FASD.Base;
|
||||||
|
using C4IT.MultiLanguage;
|
||||||
|
|
||||||
using F4SD_AdaptableIcon;
|
using F4SD_AdaptableIcon;
|
||||||
using F4SD_AdaptableIcon.Enums;
|
using F4SD_AdaptableIcon.Enums;
|
||||||
|
|
||||||
using FasdDesktopUi.Basics.Converter;
|
using FasdDesktopUi.Basics.Converter;
|
||||||
using FasdDesktopUi.Basics.UiActions;
|
using FasdDesktopUi.Basics.UiActions;
|
||||||
|
|
||||||
using static C4IT.Logging.cLogManager;
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
namespace FasdDesktopUi.Basics.Models
|
namespace FasdDesktopUi.Basics.Models
|
||||||
@@ -20,7 +25,7 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
|
|
||||||
public string TrailingText { get; set; }
|
public string TrailingText { get; set; }
|
||||||
|
|
||||||
public IconData MenuIcon { get; set; }
|
public MenuIconInfo MenuIcon { get; set; }
|
||||||
|
|
||||||
public double MenuIconSize { get; set; } = 1.0;
|
public double MenuIconSize { get; set; } = 1.0;
|
||||||
|
|
||||||
@@ -32,14 +37,36 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
|
|
||||||
public cUiActionBase UiAction { get; set; }
|
public cUiActionBase UiAction { get; set; }
|
||||||
|
|
||||||
|
public class MenuIconInfo
|
||||||
|
{
|
||||||
|
public readonly IconData Icon;
|
||||||
|
public readonly IconData? Overlay;
|
||||||
|
public readonly bool IsInactive;
|
||||||
|
public readonly string Description;
|
||||||
|
|
||||||
|
public MenuIconInfo(IconData icon, string Description = null, bool isInactive = false, IconData? overlay = null)
|
||||||
|
{
|
||||||
|
Icon = icon;
|
||||||
|
IsInactive = isInactive;
|
||||||
|
this.Description = Description;
|
||||||
|
Overlay = overlay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public cMenuDataBase()
|
public cMenuDataBase()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public cMenuDataBase(cFasdBaseConfigMenuItem menuItem)
|
public cMenuDataBase(cFasdBaseConfigMenuItem menuItem)
|
||||||
{
|
{
|
||||||
MenuText = menuItem.Names.GetValue(Default: null);
|
MenuText = menuItem.Names.GetValue(Default: null);
|
||||||
MenuIcon = IconDataConverter.Convert(menuItem.Icon);
|
MenuIcon = new MenuIconInfo(IconDataConverter.Convert(menuItem.Icon));
|
||||||
MenuSections = menuItem.Sections;
|
MenuSections = menuItem.Sections;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(menuItem.Section))
|
||||||
|
MenuSections.Add(menuItem.Section);
|
||||||
|
|
||||||
|
MenuSections = MenuSections.Distinct().ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public cMenuDataBase(cFasdQuickAction quickAction, Enums.enumActionDisplayType display) : this(quickAction)
|
public cMenuDataBase(cFasdQuickAction quickAction, Enums.enumActionDisplayType display) : this(quickAction)
|
||||||
@@ -69,7 +96,7 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
|
|
||||||
public cMenuDataBase(cFasdQuickTip quickTip) : this((cFasdBaseConfigMenuItem)quickTip)
|
public cMenuDataBase(cFasdQuickTip quickTip) : this((cFasdBaseConfigMenuItem)quickTip)
|
||||||
{
|
{
|
||||||
UiAction = new cUiQuickTipAction(quickTip) { DisplayType = Enums.enumActionDisplayType.enabled };
|
UiAction = new cUiQuickTipAction(quickTip) { DisplayType = Enums.enumActionDisplayType.enabled, Name = quickTip.Name };
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetUiActionDisplayType(Enums.enumActionDisplayType display)
|
public void SetUiActionDisplayType(Enums.enumActionDisplayType display)
|
||||||
@@ -83,7 +110,7 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
public class cMenuDataContainer : cMenuDataBase
|
public class cMenuDataContainer : cMenuDataBase
|
||||||
{
|
{
|
||||||
public string ContainerName { get; private set; }
|
public string ContainerName { get; private set; }
|
||||||
public List<cMenuDataBase> SubMenuData { get; set; }
|
public List<cMenuDataBase> SubMenuData { get; set; } = new List<cMenuDataBase>();
|
||||||
|
|
||||||
public cMenuDataContainer()
|
public cMenuDataContainer()
|
||||||
{
|
{
|
||||||
@@ -110,29 +137,95 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
MenuIcon = GetMenuIcon(firstSearchResult.Type, firstSearchResult.Infos);
|
MenuIcon = GetMenuIcon(firstSearchResult.Type, firstSearchResult.Infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public IconData GetMenuIcon(enumF4sdSearchResultClass searchResultClass, Dictionary<string, string> infos)
|
static private MenuIconInfo GetTicketIcon(Dictionary<string, string> infos)
|
||||||
|
{
|
||||||
|
bool isInactive = false;
|
||||||
|
if (infos.TryGetValue("StatusId", out var ticketStatusId))
|
||||||
|
{
|
||||||
|
if (Enum.TryParse(ticketStatusId, true, out enumTicketStatus ticketStatus))
|
||||||
|
{
|
||||||
|
switch (ticketStatus)
|
||||||
|
{
|
||||||
|
case enumTicketStatus.Closed:
|
||||||
|
isInactive = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string description = null;
|
||||||
|
var overlay = isInactive ? (IconData?)new IconData(enumInternIcons.misc_disabledOverlay) : null;
|
||||||
|
if (isInactive)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if (infos.TryGetValue("TicketType", out var ticketType))
|
||||||
|
{
|
||||||
|
if (Enum.TryParse(ticketType, true, out enumTicketType parsedTicketType))
|
||||||
|
{
|
||||||
|
switch (parsedTicketType)
|
||||||
|
{
|
||||||
|
case enumTicketType.Incident:
|
||||||
|
if (isInactive)
|
||||||
|
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Incident.Closed");
|
||||||
|
else
|
||||||
|
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Incident.Active");
|
||||||
|
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_bug_report), description, isInactive, overlay);
|
||||||
|
case enumTicketType.ServiceRequest:
|
||||||
|
if (isInactive)
|
||||||
|
description = cMultiLanguageSupport.GetItem("Searchbar.Item.ServiceRequest.Closed");
|
||||||
|
else
|
||||||
|
description = cMultiLanguageSupport.GetItem("Searchbar.Item.ServiceRequest.Active");
|
||||||
|
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_room_service), description, isInactive, overlay);
|
||||||
|
case enumTicketType.UnclassifiedTicket:
|
||||||
|
if (isInactive)
|
||||||
|
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Unclassified.Closed");
|
||||||
|
else
|
||||||
|
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Unclassified.Active");
|
||||||
|
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_confirmation_number), description, isInactive, overlay);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInactive)
|
||||||
|
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Ticket.Closed");
|
||||||
|
else
|
||||||
|
description = cMultiLanguageSupport.GetItem("Searchbar.Item.Ticket.Active");
|
||||||
|
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_mail_outline), description, isInactive, overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
static private MenuIconInfo GetVirtualSessionIcon(Dictionary<string, string> infos)
|
||||||
|
{
|
||||||
|
if (infos.TryGetValue("Status", out string status))
|
||||||
|
{
|
||||||
|
if (status == nameof(enumCitrixSessionStatus.Active))
|
||||||
|
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_cloud_queue));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_cloud_off));
|
||||||
|
}
|
||||||
|
|
||||||
|
static public MenuIconInfo GetMenuIcon(enumF4sdSearchResultClass searchResultClass, Dictionary<string, string> infos)
|
||||||
{
|
{
|
||||||
switch (searchResultClass)
|
switch (searchResultClass)
|
||||||
{
|
{
|
||||||
case enumF4sdSearchResultClass.Computer:
|
case enumF4sdSearchResultClass.Computer:
|
||||||
return new IconData(enumInternIcons.misc_computer);
|
return new MenuIconInfo(new IconData(enumInternIcons.misc_computer));
|
||||||
case enumF4sdSearchResultClass.User:
|
case enumF4sdSearchResultClass.User:
|
||||||
return new IconData(enumInternIcons.misc_user);
|
return new MenuIconInfo(new IconData(enumInternIcons.misc_user));
|
||||||
case enumF4sdSearchResultClass.Phone:
|
case enumF4sdSearchResultClass.Phone:
|
||||||
return new IconData(MaterialIcons.MaterialIconType.ic_phone);
|
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_phone));
|
||||||
case enumF4sdSearchResultClass.Ticket:
|
case enumF4sdSearchResultClass.Ticket:
|
||||||
return new IconData(enumInternIcons.misc_ticket);
|
return GetTicketIcon(infos);
|
||||||
case enumF4sdSearchResultClass.MobileDevice:
|
case enumF4sdSearchResultClass.MobileDevice:
|
||||||
return new IconData(MaterialIcons.MaterialIconType.ic_smartphone);
|
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_smartphone));
|
||||||
case enumF4sdSearchResultClass.VirtualSession:
|
case enumF4sdSearchResultClass.VirtualSession:
|
||||||
if (!infos.TryGetValue("Status", out string status))
|
return GetVirtualSessionIcon(infos);
|
||||||
return new IconData(MaterialIcons.MaterialIconType.ic_cloud_off);
|
|
||||||
else if (status == nameof(enumCitrixSessionStatus.Active))
|
|
||||||
return new IconData(MaterialIcons.MaterialIconType.ic_cloud_queue);
|
|
||||||
else
|
|
||||||
return new IconData(MaterialIcons.MaterialIconType.ic_cloud_off);
|
|
||||||
default:
|
default:
|
||||||
return new IconData(MaterialIcons.MaterialIconType.ic_more_vert);
|
return new MenuIconInfo(new IconData(MaterialIcons.MaterialIconType.ic_more_vert));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
using System;
|
using C4IT.F4SD.DisplayFormatting;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Windows;
|
|
||||||
|
|
||||||
using C4IT.F4SD.DisplayFormatting;
|
|
||||||
using C4IT.F4SD.SupportCaseProtocoll.Models;
|
using C4IT.F4SD.SupportCaseProtocoll.Models;
|
||||||
using C4IT.FASD.Base;
|
using C4IT.FASD.Base;
|
||||||
|
|
||||||
using FasdCockpitBase;
|
using FasdCockpitBase;
|
||||||
|
using FasdDesktopUi.Basics.Helper;
|
||||||
using FasdDesktopUi.Basics.Services.ProtocollService;
|
using FasdDesktopUi.Basics.Services.ProtocollService;
|
||||||
|
using FasdDesktopUi.Basics.Services.SupportCase.Processors;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
using static C4IT.Logging.cLogManager;
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
namespace FasdDesktopUi.Basics.Models
|
namespace FasdDesktopUi.Basics.Models
|
||||||
@@ -49,7 +51,7 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
cUtility.RawValueFormatter.SetDefaultCulture(new System.Globalization.CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage));
|
cUtility.RawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
|
||||||
cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
|
cUtility.RawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
|
||||||
|
|
||||||
var outputTable = dataProvider.HealthCardDataHelper.HealthCardRawData.GetTableByName(valueAdress.ValueTable, true);
|
var outputTable = dataProvider.HealthCardDataHelper.HealthCardRawData.GetTableByName(valueAdress.ValueTable, true);
|
||||||
@@ -193,6 +195,33 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class cNamedParameterEntryCaseNotes : cNamedParameterEntryBase
|
||||||
|
{
|
||||||
|
private readonly bool _getHtmlAsDefaultValue;
|
||||||
|
|
||||||
|
public cNamedParameterEntryCaseNotes(cSupportCaseDataProvider dataProvider, bool getHtmlAsDefaultValue) : base(dataProvider)
|
||||||
|
{
|
||||||
|
_getHtmlAsDefaultValue = getHtmlAsDefaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetValue()
|
||||||
|
{
|
||||||
|
if (_getHtmlAsDefaultValue)
|
||||||
|
return GetHtmlValue();
|
||||||
|
|
||||||
|
StringBuilder caseNotesStringBuilder = new StringBuilder();
|
||||||
|
cRichTextBoxHelper.TraverseBlockAsUnicode(dataProvider.CaseNotes.Blocks, caseNotesStringBuilder);
|
||||||
|
return caseNotesStringBuilder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHtmlValue()
|
||||||
|
{
|
||||||
|
StringBuilder caseNotesHtmlStringBuilder = new StringBuilder();
|
||||||
|
cRichTextBoxHelper.TraverseBlockAsHtml(dataProvider.CaseNotes.Blocks, caseNotesHtmlStringBuilder);
|
||||||
|
return caseNotesHtmlStringBuilder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class cNamedParameterList : Dictionary<string, cNamedParameterEntryBase>
|
public class cNamedParameterList : Dictionary<string, cNamedParameterEntryBase>
|
||||||
{
|
{
|
||||||
public cNamedParameterList()
|
public cNamedParameterList()
|
||||||
@@ -204,8 +233,11 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Add("F4SD_QuickActionProtocolLast", new cNamedParameterEntryQuickActionResult(dataProvider));
|
Add(SupportCaseProcessor.QuickActionProtocolLastNamedParameterName, new cNamedParameterEntryQuickActionResult(dataProvider));
|
||||||
Add("F4SD_QuickActionProtocol", new cNamedParameterEntryQuickActionResultProtocol(dataProvider));
|
Add(SupportCaseProcessor.QuickActionProtocolNamedParameterName, new cNamedParameterEntryQuickActionResultProtocol(dataProvider));
|
||||||
|
|
||||||
|
Add(SupportCaseProcessor.CaseNotesNamedParameterName, new cNamedParameterEntryCaseNotes(dataProvider, false));
|
||||||
|
Add(SupportCaseProcessor.CaseNotesHtmlNamedParameterName, new cNamedParameterEntryCaseNotes(dataProvider, true));
|
||||||
}
|
}
|
||||||
catch (Exception E)
|
catch (Exception E)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
using FasdDesktopUi.Basics.UserControls;
|
using FasdDesktopUi.Basics.Models.QuickActionOutput;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace FasdDesktopUi.Basics.Models
|
namespace FasdDesktopUi.Basics.Models
|
||||||
{
|
{
|
||||||
@@ -13,7 +10,7 @@ namespace FasdDesktopUi.Basics.Models
|
|||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string AffectedDeviceName { get; set; }
|
public string AffectedDeviceName { get; set; }
|
||||||
public bool WasRunningOnAffectedDevice { get; set; }
|
public bool WasRunningOnAffectedDevice { get; set; }
|
||||||
public QuickActionStatusMonitor.cQuickActionOutput QuickActionOutput { get; set; }
|
public cQuickActionOutput QuickActionOutput { get; set; }
|
||||||
public List<QuickActionStatusMonitor.cQuickActionMeasureValue> MeasureValues { get; set; }
|
public List<cQuickActionMeasureValue> MeasureValues { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using C4IT.F4SD.DisplayFormatting;
|
||||||
|
using C4IT.FASD.Base;
|
||||||
|
using C4IT.MultiLanguage;
|
||||||
|
|
||||||
|
namespace FasdDesktopUi.Basics.Models.QuickActionOutput
|
||||||
|
{
|
||||||
|
|
||||||
|
public class cQuickActionMeasureValue
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public cMultiLanguageDictionary Names { get; set; }
|
||||||
|
public object Value { get; set; }
|
||||||
|
public object PostValue { get; set; }
|
||||||
|
|
||||||
|
public object Difference
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (Display)
|
||||||
|
{
|
||||||
|
case RawValueType.INTEGER:
|
||||||
|
case RawValueType.PERCENT:
|
||||||
|
case RawValueType.PERCENT100:
|
||||||
|
case RawValueType.PERCENT1000:
|
||||||
|
case RawValueType.BYTES:
|
||||||
|
var valueDouble = cF4SDHealthCardRawData.GetDouble(Value);
|
||||||
|
var postValueDouble = cF4SDHealthCardRawData.GetDouble(PostValue);
|
||||||
|
|
||||||
|
if (valueDouble != null && postValueDouble != null)
|
||||||
|
return postValueDouble - valueDouble;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RawValueType Display { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
using C4IT.F4SD.DisplayFormatting;
|
||||||
|
using C4IT.FASD.Base;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
|
namespace FasdDesktopUi.Basics.Models.QuickActionOutput
|
||||||
|
{
|
||||||
|
public abstract class cQuickActionOutput
|
||||||
|
{
|
||||||
|
protected const string veiledText = "********";
|
||||||
|
|
||||||
|
protected readonly IRawValueFormatter _rawValueFormatter = new RawValueFormatter();
|
||||||
|
|
||||||
|
public cQuickActionOutput(cF4sdQuickActionRevision.cOutput scriptOutput)
|
||||||
|
{
|
||||||
|
_rawValueFormatter.SetDefaultCulture(cFasdCockpitConfig.Instance.SelectedCulture);
|
||||||
|
_rawValueFormatter.SetDefaultTimeZone(TimeZoneInfo.Local);
|
||||||
|
ErrorCode = scriptOutput.ErrorCode;
|
||||||
|
ErrorDescription = scriptOutput.ErrorDescription;
|
||||||
|
ResultCode = scriptOutput.ResultCode.GetValueOrDefault();
|
||||||
|
IsError = HasError(scriptOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
public cSupportCaseDataProvider DataProvider { get; private set; }
|
||||||
|
public enumQuickActionSuccess? ResultCode { get; set; }
|
||||||
|
public int? ErrorCode { get; set; }
|
||||||
|
public string ErrorDescription { get; set; }
|
||||||
|
|
||||||
|
public bool IsError { get; private set; }
|
||||||
|
|
||||||
|
internal static KeyValuePair<string, RawValueType> GetDisplayType(dynamic columnTypeObject)
|
||||||
|
{
|
||||||
|
var output = new KeyValuePair<string, RawValueType>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var columnType = columnTypeObject.ToObject<dynamic>();
|
||||||
|
string name = string.Empty;
|
||||||
|
RawValueType type = RawValueType.STRING;
|
||||||
|
|
||||||
|
|
||||||
|
if (columnType.Name != null)
|
||||||
|
if (columnType.Name is Newtonsoft.Json.Linq.JValue nameJValue)
|
||||||
|
name = nameJValue.Value.ToString();
|
||||||
|
|
||||||
|
if (columnType.Type != null)
|
||||||
|
if (columnType.Type is Newtonsoft.Json.Linq.JValue typeJValue)
|
||||||
|
if (Enum.TryParse(typeJValue.Value.ToString(), out RawValueType typeJValueType))
|
||||||
|
type = typeJValueType;
|
||||||
|
|
||||||
|
output = new KeyValuePair<string, RawValueType>(name, type);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static cQuickActionOutput GetQuickActionOutput(cF4sdQuickActionRevision.cOutput scriptOutput, cSupportCaseDataProvider dataProvider)
|
||||||
|
{
|
||||||
|
if (scriptOutput == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (scriptOutput?.Values == null)
|
||||||
|
{
|
||||||
|
var output = new cQuickActionOutputSingle(scriptOutput) { DataProvider = dataProvider };
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
else if (scriptOutput.Values is JArray scriptValueJArray)
|
||||||
|
{
|
||||||
|
var scriptValues = scriptValueJArray.ToObject<List<dynamic>>();
|
||||||
|
if (scriptValues != null && scriptValues.Count > 0)
|
||||||
|
{
|
||||||
|
var output = new cQuickActionOutputList(scriptOutput) { DataProvider = dataProvider };
|
||||||
|
|
||||||
|
foreach (var scriptValue in scriptValues)
|
||||||
|
{
|
||||||
|
if (scriptValue is JObject scriptValueJObject)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var scriptValueHelperDictionary = scriptValueJObject.ToObject<Dictionary<string, object>>();
|
||||||
|
output.Values.Add(scriptValueHelperDictionary.ToList());
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (scriptOutput.Values is JObject scriptValueJObject)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var output = new cQuickActionOutputObject(scriptOutput) { DataProvider = dataProvider };
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new cQuickActionOutputSingle(scriptOutput) { DataProvider = dataProvider };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasError(cF4sdQuickActionRevision.cOutput quickActionOutput)
|
||||||
|
{
|
||||||
|
if ((quickActionOutput?.ResultCode == null || quickActionOutput?.ResultCode == enumQuickActionSuccess.finished || quickActionOutput?.ResultCode == enumQuickActionSuccess.successfull)
|
||||||
|
&& (quickActionOutput?.ErrorCode == null || quickActionOutput?.ErrorCode == 0)
|
||||||
|
&& string.IsNullOrEmpty(quickActionOutput?.ErrorDescription))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
using C4IT.F4SD.DisplayFormatting;
|
||||||
|
using C4IT.FASD.Base;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
|
namespace FasdDesktopUi.Basics.Models.QuickActionOutput
|
||||||
|
{
|
||||||
|
public class cQuickActionOutputList : cQuickActionOutput
|
||||||
|
{
|
||||||
|
public cQuickActionOutputList(cF4sdQuickActionRevision.cOutput scriptOutput) : base(scriptOutput)
|
||||||
|
{
|
||||||
|
InstantiateDisplayTypes(scriptOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, RawValueType> DisplayTypes { get; set; } = new Dictionary<string, RawValueType>();
|
||||||
|
public List<List<KeyValuePair<string, object>>> Values { get; set; } = new List<List<KeyValuePair<string, object>>>();
|
||||||
|
|
||||||
|
private void InstantiateDisplayTypes(cF4sdQuickActionRevision.cOutput scriptOutput)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (scriptOutput.ColumnTypes is Newtonsoft.Json.Linq.JArray columnTypeJArray)
|
||||||
|
{
|
||||||
|
var columnTypes = columnTypeJArray.ToObject<List<dynamic>>();
|
||||||
|
if (columnTypes != null && columnTypes.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var columnTypeObject in columnTypes)
|
||||||
|
{
|
||||||
|
var displayType = GetDisplayType(columnTypeObject);
|
||||||
|
DisplayTypes[displayType.Key] = displayType.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (scriptOutput.ColumnTypes is Newtonsoft.Json.Linq.JObject columnTypeJObject)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var displayType = GetDisplayType(columnTypeJObject);
|
||||||
|
|
||||||
|
DisplayTypes[displayType.Key] = displayType.Value;
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDisplayValue(int row, int column, Dictionary<string, cColumnOutputFormatting> columnOutputFormattings, bool getSecretValue = false)
|
||||||
|
{
|
||||||
|
string output = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RawValueType displayType = RawValueType.STRING;
|
||||||
|
DisplayTypes.TryGetValue(Values[row][column].Key, out displayType);
|
||||||
|
output = _rawValueFormatter.GetDisplayValue(Values[row][column].Value, displayType);
|
||||||
|
|
||||||
|
if (columnOutputFormattings != null && columnOutputFormattings.TryGetValue(Values[row][column].Key, out var outputFormatting))
|
||||||
|
{
|
||||||
|
if (outputFormatting.Hidden)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
if (outputFormatting.IsSecret && !getSecretValue)
|
||||||
|
return veiledText;
|
||||||
|
|
||||||
|
if (outputFormatting.DisplayType != null)
|
||||||
|
output = _rawValueFormatter.GetDisplayValue(Values[row][column].Value, outputFormatting.DisplayType.Value);
|
||||||
|
|
||||||
|
if (outputFormatting.Translation != null)
|
||||||
|
{
|
||||||
|
var abstractTranslation = cF4SDHealthCardConfig.GetTranslationsWithName(DataProvider?.HealthCardDataHelper?.SelectedHealthCard, outputFormatting.Translation);
|
||||||
|
if (abstractTranslation != null && abstractTranslation is cHealthCardTranslator translator)
|
||||||
|
{
|
||||||
|
output = translator.DefaultTranslation?.Translation.GetValue() ?? Values[row].ToList()[column].Value.ToString();
|
||||||
|
|
||||||
|
foreach (var translation in translator.Translations)
|
||||||
|
{
|
||||||
|
if (translation.Values.Any(value => value.Equals(Values[row].ToList()[column].Value.ToString(), StringComparison.InvariantCultureIgnoreCase)))
|
||||||
|
output = translation.Translation.GetValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
using C4IT.F4SD.DisplayFormatting;
|
||||||
|
using C4IT.FASD.Base;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using static C4IT.Logging.cLogManager;
|
||||||
|
|
||||||
|
namespace FasdDesktopUi.Basics.Models.QuickActionOutput
|
||||||
|
{
|
||||||
|
public class cQuickActionOutputObject : cQuickActionOutput
|
||||||
|
{
|
||||||
|
public Dictionary<string, RawValueType> DisplayTypes { get; set; } = new Dictionary<string, RawValueType>();
|
||||||
|
public List<KeyValuePair<string, object>> Values { get; set; } = new List<KeyValuePair<string, object>>();
|
||||||
|
|
||||||
|
public cQuickActionOutputObject(cF4sdQuickActionRevision.cOutput scriptOutput) : base(scriptOutput)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InstantiateDisplayTypes(scriptOutput);
|
||||||
|
InstantiateValues(scriptOutput);
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InstantiateDisplayTypes(cF4sdQuickActionRevision.cOutput scriptOutput)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (scriptOutput.ColumnTypes is Newtonsoft.Json.Linq.JArray columnTypeJArray)
|
||||||
|
{
|
||||||
|
var columnTypes = columnTypeJArray.ToObject<List<dynamic>>();
|
||||||
|
if (columnTypes != null && columnTypes.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var columnTypeObject in columnTypes)
|
||||||
|
{
|
||||||
|
var displayType = GetDisplayType(columnTypeObject);
|
||||||
|
DisplayTypes[displayType.Key] = displayType.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (scriptOutput.ColumnTypes is Newtonsoft.Json.Linq.JObject columnTypeJObject)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var displayType = GetDisplayType(columnTypeJObject);
|
||||||
|
|
||||||
|
DisplayTypes[displayType.Key] = displayType.Value;
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InstantiateValues(cF4sdQuickActionRevision.cOutput scriptOutput)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!(scriptOutput.Values is JObject valuesJObject))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (valuesJObject.Properties() == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var property in valuesJObject.Properties())
|
||||||
|
{
|
||||||
|
Values.Add(new KeyValuePair<string, object>(property.Name, property.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDisplayValue(int index, Dictionary<string, cColumnOutputFormatting> columnOutputFormattings, bool getSecretValue = false)
|
||||||
|
{
|
||||||
|
string output = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Values.Count <= index)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var selectedItem = Values[index];
|
||||||
|
|
||||||
|
RawValueType displayType = RawValueType.STRING;
|
||||||
|
DisplayTypes.TryGetValue(selectedItem.Key, out displayType);
|
||||||
|
output = _rawValueFormatter.GetDisplayValue(selectedItem.Value, displayType);
|
||||||
|
|
||||||
|
if (columnOutputFormattings != null && columnOutputFormattings.TryGetValue(selectedItem.Key, out var outputFormatting))
|
||||||
|
{
|
||||||
|
if (outputFormatting.Hidden)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
if (outputFormatting.IsSecret && !getSecretValue)
|
||||||
|
return veiledText;
|
||||||
|
|
||||||
|
if (outputFormatting.DisplayType != null)
|
||||||
|
output = _rawValueFormatter.GetDisplayValue(selectedItem.Value, outputFormatting.DisplayType.Value);
|
||||||
|
|
||||||
|
if (outputFormatting.Translation != null)
|
||||||
|
{
|
||||||
|
var abstractTranslation = cF4SDHealthCardConfig.GetTranslationsWithName(DataProvider?.HealthCardDataHelper?.SelectedHealthCard, outputFormatting.Translation);
|
||||||
|
if (abstractTranslation != null && abstractTranslation is cHealthCardTranslator translator)
|
||||||
|
{
|
||||||
|
output = translator.DefaultTranslation?.Translation.GetValue() ?? selectedItem.Value.ToString();
|
||||||
|
|
||||||
|
foreach (var translation in translator.Translations)
|
||||||
|
{
|
||||||
|
if (translation.Values.Any(value => value.Equals(selectedItem.Value.ToString(), StringComparison.InvariantCultureIgnoreCase)))
|
||||||
|
output = translation.Translation.GetValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception E)
|
||||||
|
{
|
||||||
|
LogException(E);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user