Added support for macros in payload when publishing

This commit is contained in:
Mark van Renswoude 2022-01-14 11:52:31 +01:00
parent a4f85b0f07
commit 4baa578e89
20 changed files with 444 additions and 32 deletions

View File

@ -0,0 +1,22 @@
namespace PettingZoo.Core.Macros
{
public abstract class BasePayloadMacro : IPayloadMacro
{
public string DisplayName { get; }
public string MacroText { get; }
public string MacroCommand { get; }
protected BasePayloadMacro(string macroCommand, string displayName)
{
MacroCommand = macroCommand;
DisplayName = displayName;
MacroText = "{{" + macroCommand + "}}";
}
public abstract string GetValue();
}
}

View File

@ -0,0 +1,18 @@
using System;
namespace PettingZoo.Core.Macros
{
public class JsonDateTimePayloadMacro : BasePayloadMacro
{
public JsonDateTimePayloadMacro()
: base("JsonUtcNow", "Current date/time (yyyy-mm-ddThh:mm:ss.mmmZ)")
{
}
public override string GetValue()
{
return DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'");
}
}
}

View File

@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace PettingZoo.Core.Macros
{
public interface IPayloadMacroProcessor
{
string Apply(string payload);
IEnumerable<IPayloadMacro> Macros { get; }
}
public interface IPayloadMacro
{
public string DisplayName { get; }
public string MacroText { get; }
}
}

View File

@ -0,0 +1,18 @@
using System;
namespace PettingZoo.Core.Macros
{
public class NewGuidPayloadMacro : BasePayloadMacro
{
public NewGuidPayloadMacro()
: base("NewGuid", "Generate GUID")
{
}
public override string GetValue()
{
return Guid.NewGuid().ToString();
}
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace PettingZoo.Core.Macros
{
public class PayloadMacroProcessor : IPayloadMacroProcessor
{
private readonly BasePayloadMacro[] macros;
public IEnumerable<IPayloadMacro> Macros => macros;
public PayloadMacroProcessor()
{
macros = new BasePayloadMacro[]
{
new NewGuidPayloadMacro(),
new JsonDateTimePayloadMacro()
};
}
// For now we only support simple one-keyboard macros, but this could be extended with parameters if required
private static readonly Regex MacroRegex = new("{{(.+?)}}", RegexOptions.Compiled);
public string Apply(string payload)
{
return MacroRegex.Replace(payload, match =>
{
var macroCommand = match.Groups[1].Value.Trim();
var macro = macros.FirstOrDefault(m => string.Equals(m.MacroCommand, macroCommand, StringComparison.CurrentCultureIgnoreCase));
return macro != null
? macro.GetValue()
: match.Groups[0].Value;
});
}
}
}

View File

@ -148,7 +148,7 @@
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="UI\Tab\Publisher\PayloadEditorStrings.resx">
<Generator>ResXFileCodeGenerator</Generator>
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>PayloadEditorStrings.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="UI\Tab\Publisher\TapetiPublisherViewStrings.resx">

View File

@ -6,6 +6,7 @@ using System.Windows.Markup;
using PettingZoo.Core.Connection;
using PettingZoo.Core.ExportImport;
using PettingZoo.Core.Generator;
using PettingZoo.Core.Macros;
using PettingZoo.Core.Settings;
using PettingZoo.RabbitMQ;
using PettingZoo.Settings.LiteDB;
@ -84,6 +85,7 @@ namespace PettingZoo
container.Register<IExampleGenerator, TapetiClassLibraryExampleGenerator>();
container.RegisterSingleton<ITabHostProvider, TabHostProvider>();
container.Register<ITabFactory, ViewTabFactory>();
container.RegisterSingleton<IPayloadMacroProcessor, PayloadMacroProcessor>();
container.RegisterInstance<IExportImportFormatProvider>(new ExportImportFormatProvider(
new TapetiCmdExportFormat(),

View File

@ -21,18 +21,36 @@
</StackPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" Visibility="{Binding ValidationVisibility}" Margin="0,8,0,0">
<Image Source="{svgc:SvgImage Source=/Images/Ok.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="4" Visibility="{Binding ValidationOk}" />
<Image Source="{svgc:SvgImage Source=/Images/Error.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="4" Visibility="{Binding ValidationError}" />
<Image Source="{svgc:SvgImage Source=/Images/Busy.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="4" Visibility="{Binding ValidationValidating}" />
<Image Source="{svgc:SvgImage Source=/Images/Ok.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="1,4,0,0" Visibility="{Binding ValidationOk}" />
<Image Source="{svgc:SvgImage Source=/Images/Error.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="1,4,0,0" Visibility="{Binding ValidationError}" />
<Image Source="{svgc:SvgImage Source=/Images/Busy.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="1,4,0,0" Visibility="{Binding ValidationValidating}" />
<TextBlock Text="{Binding ValidationMessage}" Margin="4" />
</StackPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" Margin="0,8,0,0">
<CheckBox Content="{x:Static publisher:PayloadEditorStrings.CheckEnableMacros}" VerticalAlignment="Center" IsChecked="{Binding EnableMacros}" />
</StackPanel>
<Border Style="{StaticResource ControlBorder}" Name="EditorBorder">
<avalonedit:TextEditor
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
Name="Editor"
SyntaxHighlighting="{Binding SyntaxHighlighting}"
Style="{StaticResource Payload}" />
Style="{StaticResource Payload}">
<avalonedit:TextEditor.ContextMenu>
<ContextMenu Opened="ContextMenu_OnOpened">
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuUndo}" Name="ContextMenuUndo" Click="Undo_Click" InputGestureText="Ctrl+Z" />
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuRedo}" Name="ContextMenuRedo" Click="Redo_Click" InputGestureText="Ctrl+Y "/>
<Separator/>
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuCut}" Name="ContextMenuCut" Click="Cut_Click" InputGestureText="Ctrl+X "/>
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuCopy}" Name="ContextMenuCopy" Click="Copy_Click" InputGestureText="Ctrl+C "/>
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuPaste}" Name="ContextMenuPaste" Click="Paste_Click" InputGestureText="Ctrl+V "/>
<Separator/>
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuInsertMacro}" Name="ContextMenuInsertMacro" />
</ContextMenu>
</avalonedit:TextEditor.ContextMenu>
</avalonedit:TextEditor>
</Border>
</DockPanel>
</UserControl>

View File

@ -2,7 +2,9 @@
using System.Reactive.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using PettingZoo.Core.Macros;
using PettingZoo.Core.Validation;
namespace PettingZoo.UI.Tab.Publisher
@ -88,6 +90,32 @@ namespace PettingZoo.UI.Tab.Publisher
}
public static readonly DependencyProperty EnableMacrosProperty
= DependencyProperty.Register(
"EnableMacros",
typeof(bool),
typeof(PayloadEditorControl),
new FrameworkPropertyMetadata(false)
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
}
);
public bool EnableMacros
{
get => viewModel.EnableMacros;
set
{
if (value == viewModel.EnableMacros)
return;
SetValue(EnableMacrosProperty, value);
viewModel.EnableMacros = value;
}
}
public IPayloadValidator? Validator
{
get => viewModel.Validator;
@ -95,6 +123,21 @@ namespace PettingZoo.UI.Tab.Publisher
}
private IPayloadMacroProcessor? macroProcessor;
public IPayloadMacroProcessor? MacroProcessor
{
get => macroProcessor;
set
{
if (value == macroProcessor)
return;
macroProcessor = value;
UpdateMacroContextMenu();
}
}
private readonly ErrorHighlightingTransformer errorHighlightingTransformer = new();
public PayloadEditorControl()
@ -123,6 +166,12 @@ namespace PettingZoo.UI.Tab.Publisher
viewModel.Payload = value;
});
this.OnPropertyChanges<bool>(EnableMacrosProperty)
.ObserveOn(SynchronizationContext.Current!)
.Subscribe(value =>
{
viewModel.EnableMacros = value;
});
viewModel.PropertyChanged += (_, args) =>
{
@ -139,6 +188,10 @@ namespace PettingZoo.UI.Tab.Publisher
case nameof(viewModel.Payload):
SetValue(PayloadProperty, viewModel.Payload);
break;
case nameof(viewModel.EnableMacros):
SetValue(EnableMacrosProperty, viewModel.EnableMacros);
break;
}
};
@ -207,5 +260,70 @@ namespace PettingZoo.UI.Tab.Publisher
// so I've moved the ViewModel one level down to get the best of both worlds...
DataContextContainer.DataContext = viewModel;
}
private void UpdateMacroContextMenu()
{
ContextMenuInsertMacro.Items.Clear();
if (macroProcessor == null)
return;
foreach (var macro in macroProcessor.Macros)
{
var macroMenuItem = new MenuItem
{
Header = macro.DisplayName
};
macroMenuItem.Click += (_, _) =>
{
Editor.SelectedText = macro.MacroText;
var length = Editor.SelectionLength;
Editor.SelectionLength = 0;
Editor.SelectionStart += length;
viewModel.EnableMacros = true;
};
ContextMenuInsertMacro.Items.Add(macroMenuItem);
}
}
private void Undo_Click(object sender, RoutedEventArgs e)
{
Editor.Undo();
}
private void Redo_Click(object sender, RoutedEventArgs e)
{
Editor.Redo();
}
private void Cut_Click(object sender, RoutedEventArgs e)
{
Editor.Cut();
}
private void Copy_Click(object sender, RoutedEventArgs e)
{
Editor.Copy();
}
private void Paste_Click(object sender, RoutedEventArgs e)
{
Editor.Paste();
}
private void ContextMenu_OnOpened(object sender, RoutedEventArgs e)
{
ContextMenuUndo.IsEnabled = Editor.CanUndo;
ContextMenuRedo.IsEnabled = Editor.CanRedo;
ContextMenuCut.IsEnabled = Editor.SelectionLength > 0;
ContextMenuCopy.IsEnabled = Editor.SelectionLength > 0;
ContextMenuPaste.IsEnabled = Clipboard.ContainsText();
}
}
}

View File

@ -22,7 +22,7 @@ namespace PettingZoo.UI.Tab.Publisher {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class PayloadEditorStrings {
public class PayloadEditorStrings {
private static global::System.Resources.ResourceManager resourceMan;
@ -36,7 +36,7 @@ namespace PettingZoo.UI.Tab.Publisher {
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.UI.Tab.Publisher.PayloadEditorStrings", typeof(PayloadEditorStrings).Assembly);
@ -51,7 +51,7 @@ namespace PettingZoo.UI.Tab.Publisher {
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
@ -60,10 +60,19 @@ namespace PettingZoo.UI.Tab.Publisher {
}
}
/// <summary>
/// Looks up a localized string similar to Enable macros (right-click editor to insert).
/// </summary>
public static string CheckEnableMacros {
get {
return ResourceManager.GetString("CheckEnableMacros", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to JSON.
/// </summary>
internal static string ContentTypeJson {
public static string ContentTypeJson {
get {
return ResourceManager.GetString("ContentTypeJson", resourceCulture);
}
@ -72,7 +81,7 @@ namespace PettingZoo.UI.Tab.Publisher {
/// <summary>
/// Looks up a localized string similar to Other.
/// </summary>
internal static string ContentTypeOther {
public static string ContentTypeOther {
get {
return ResourceManager.GetString("ContentTypeOther", resourceCulture);
}
@ -81,16 +90,79 @@ namespace PettingZoo.UI.Tab.Publisher {
/// <summary>
/// Looks up a localized string similar to Plain text.
/// </summary>
internal static string ContentTypePlain {
public static string ContentTypePlain {
get {
return ResourceManager.GetString("ContentTypePlain", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Copy.
/// </summary>
public static string ContextMenuCopy {
get {
return ResourceManager.GetString("ContextMenuCopy", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cut.
/// </summary>
public static string ContextMenuCut {
get {
return ResourceManager.GetString("ContextMenuCut", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Insert macro.
/// </summary>
public static string ContextMenuInsertMacro {
get {
return ResourceManager.GetString("ContextMenuInsertMacro", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Paste.
/// </summary>
public static string ContextMenuPaste {
get {
return ResourceManager.GetString("ContextMenuPaste", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Redo.
/// </summary>
public static string ContextMenuRedo {
get {
return ResourceManager.GetString("ContextMenuRedo", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Undo.
/// </summary>
public static string ContextMenuUndo {
get {
return ResourceManager.GetString("ContextMenuUndo", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show available macros.
/// </summary>
public static string ShowMacrosHint {
get {
return ResourceManager.GetString("ShowMacrosHint", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid: {0}.
/// </summary>
internal static string ValidationError {
public static string ValidationError {
get {
return ResourceManager.GetString("ValidationError", resourceCulture);
}
@ -99,7 +171,7 @@ namespace PettingZoo.UI.Tab.Publisher {
/// <summary>
/// Looks up a localized string similar to Valid.
/// </summary>
internal static string ValidationOk {
public static string ValidationOk {
get {
return ResourceManager.GetString("ValidationOk", resourceCulture);
}
@ -108,7 +180,7 @@ namespace PettingZoo.UI.Tab.Publisher {
/// <summary>
/// Looks up a localized string similar to Valid syntax.
/// </summary>
internal static string ValidationOkSyntax {
public static string ValidationOkSyntax {
get {
return ResourceManager.GetString("ValidationOkSyntax", resourceCulture);
}
@ -117,7 +189,7 @@ namespace PettingZoo.UI.Tab.Publisher {
/// <summary>
/// Looks up a localized string similar to Validating....
/// </summary>
internal static string ValidationValidating {
public static string ValidationValidating {
get {
return ResourceManager.GetString("ValidationValidating", resourceCulture);
}

View File

@ -117,6 +117,9 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CheckEnableMacros" xml:space="preserve">
<value>Enable macros (right-click editor to insert)</value>
</data>
<data name="ContentTypeJson" xml:space="preserve">
<value>JSON</value>
</data>
@ -126,6 +129,27 @@
<data name="ContentTypePlain" xml:space="preserve">
<value>Plain text</value>
</data>
<data name="ContextMenuCopy" xml:space="preserve">
<value>Copy</value>
</data>
<data name="ContextMenuCut" xml:space="preserve">
<value>Cut</value>
</data>
<data name="ContextMenuInsertMacro" xml:space="preserve">
<value>Insert macro</value>
</data>
<data name="ContextMenuPaste" xml:space="preserve">
<value>Paste</value>
</data>
<data name="ContextMenuRedo" xml:space="preserve">
<value>Redo</value>
</data>
<data name="ContextMenuUndo" xml:space="preserve">
<value>Undo</value>
</data>
<data name="ShowMacrosHint" xml:space="preserve">
<value>Show available macros</value>
</data>
<data name="ValidationError" xml:space="preserve">
<value>Invalid: {0}</value>
</data>

View File

@ -2,6 +2,7 @@
using System.ComponentModel;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Input;
using ICSharpCode.AvalonEdit.Highlighting;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@ -60,10 +61,11 @@ namespace PettingZoo.UI.Tab.Publisher
private string contentType = ContentTypeJson;
private PayloadEditorContentType contentTypeSelection = PayloadEditorContentType.Json;
private bool fixedJson;
private ValidationInfo validationInfo = new(ValidationStatus.OkSyntax);
private string payload = "";
private bool enableMacros;
public string ContentType
@ -136,6 +138,7 @@ namespace PettingZoo.UI.Tab.Publisher
public Visibility ContentTypeVisibility => FixedJson ? Visibility.Collapsed : Visibility.Visible;
public string Payload
{
get => payload;
@ -143,6 +146,13 @@ namespace PettingZoo.UI.Tab.Publisher
}
public bool EnableMacros
{
get => enableMacros;
set => SetField(ref enableMacros, value);
}
public IHighlightingDefinition? SyntaxHighlighting => ContentTypeSelection == PayloadEditorContentType.Json
? HighlightingManager.Instance.GetDefinition(@"Json")
: null;

View File

@ -5,6 +5,7 @@ using System.Windows.Controls;
using System.Windows.Input;
using PettingZoo.Core.Connection;
using PettingZoo.Core.Generator;
using PettingZoo.Core.Macros;
using PettingZoo.WPF.ViewModel;
namespace PettingZoo.UI.Tab.Publisher
@ -20,6 +21,7 @@ namespace PettingZoo.UI.Tab.Publisher
{
private readonly IConnection connection;
private readonly IExampleGenerator exampleGenerator;
private readonly IPayloadMacroProcessor payloadMacroProcessor;
private readonly ITabFactory tabFactory;
private bool sendToExchange = true;
@ -155,10 +157,11 @@ namespace PettingZoo.UI.Tab.Publisher
string IPublishDestination.RoutingKey => SendToExchange ? RoutingKey : Queue;
public PublisherViewModel(ITabFactory tabFactory, IConnection connection, IExampleGenerator exampleGenerator, ReceivedMessageInfo? fromReceivedMessage = null)
public PublisherViewModel(ITabFactory tabFactory, IConnection connection, IExampleGenerator exampleGenerator, IPayloadMacroProcessor payloadMacroProcessor, ReceivedMessageInfo? fromReceivedMessage = null)
{
this.connection = connection;
this.exampleGenerator = exampleGenerator;
this.payloadMacroProcessor = payloadMacroProcessor;
this.tabFactory = tabFactory;
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
@ -207,7 +210,7 @@ namespace PettingZoo.UI.Tab.Publisher
if (rawPublisherView == null)
{
rawPublisherViewModel = new RawPublisherViewModel(connection, this);
rawPublisherViewModel = new RawPublisherViewModel(connection, this, payloadMacroProcessor);
rawPublisherViewModel.PublishCommand.CanExecuteChanged += (_, _) =>
{
publishCommand.RaiseCanExecuteChanged();
@ -228,7 +231,7 @@ namespace PettingZoo.UI.Tab.Publisher
if (tapetiPublisherView == null)
{
tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this, exampleGenerator);
tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this, exampleGenerator, payloadMacroProcessor);
tapetiPublisherViewModel.PublishCommand.CanExecuteChanged += (_, _) =>
{
publishCommand.RaiseCanExecuteChanged();
@ -263,14 +266,14 @@ namespace PettingZoo.UI.Tab.Publisher
if (TapetiPublisherViewModel.IsTapetiMessage(fromReceivedMessage))
{
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this, exampleGenerator, fromReceivedMessage);
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this, exampleGenerator, payloadMacroProcessor, fromReceivedMessage);
tapetiPublisherView = new TapetiPublisherView(tapetiPublisherViewModel);
MessageType = MessageType.Tapeti;
}
else
{
var rawPublisherViewModel = new RawPublisherViewModel(connection, this, fromReceivedMessage);
var rawPublisherViewModel = new RawPublisherViewModel(connection, this, payloadMacroProcessor, fromReceivedMessage);
rawPublisherView = new RawPublisherView(rawPublisherViewModel);
MessageType = MessageType.Raw;
@ -306,7 +309,7 @@ namespace PettingZoo.UI.Tab.Publisher
public class DesignTimePublisherViewModel : PublisherViewModel
{
public DesignTimePublisherViewModel() : base(null!, null!, null!)
public DesignTimePublisherViewModel() : base(null!, null!, null!, null!)
{
}

View File

@ -131,6 +131,7 @@
</Button>
<Label Grid.Row="14" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPayload}" />
<publisher:PayloadEditorControl Grid.Row="14" Grid.Column="1" Payload="{Binding Payload}" ContentType="{Binding ContentType}" Height="350"/>
<publisher:PayloadEditorControl Grid.Row="14" Grid.Column="1" Payload="{Binding Payload}" ContentType="{Binding ContentType}" Height="350" x:Name="PayloadEditor"
EnableMacros="{Binding EnableMacros}" />
</controls:GridLayout>
</UserControl>

View File

@ -3,6 +3,7 @@ using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using PettingZoo.Core.Macros;
namespace PettingZoo.UI.Tab.Publisher
{
@ -22,6 +23,8 @@ namespace PettingZoo.UI.Tab.Publisher
DataContext = viewModel;
InitializeComponent();
PayloadEditor.MacroProcessor = viewModel.PayloadMacroProcessor;
checkEmptyHeaderTimer = new DispatcherTimer();
checkEmptyHeaderTimer.Tick += CheckEmptyHeaderTimerOnTick;
checkEmptyHeaderTimer.Interval = TimeSpan.FromMilliseconds(50);

View File

@ -7,6 +7,7 @@ using System.Text;
using System.Windows;
using System.Windows.Input;
using PettingZoo.Core.Connection;
using PettingZoo.Core.Macros;
using PettingZoo.WPF.ViewModel;
namespace PettingZoo.UI.Tab.Publisher
@ -32,6 +33,7 @@ namespace PettingZoo.UI.Tab.Publisher
private string typeProperty = "";
private string userId = "";
private string payload = "";
private bool enableMacros;
@ -118,6 +120,12 @@ namespace PettingZoo.UI.Tab.Publisher
set => SetField(ref payload, value, delegateCommandsChanged: new [] { publishCommand });
}
public bool EnableMacros
{
get => enableMacros;
set => SetField(ref enableMacros, value);
}
public ObservableCollection<Header> Headers { get; } = new();
@ -125,6 +133,8 @@ namespace PettingZoo.UI.Tab.Publisher
public ICommand PublishCommand => publishCommand;
public ICommand PropertiesExpandCollapseCommand => propertiesExpandCollapseCommand;
public IPayloadMacroProcessor PayloadMacroProcessor { get; }
public bool PropertiesExpanded
{
@ -145,8 +155,10 @@ namespace PettingZoo.UI.Tab.Publisher
protected Header LastHeader;
public RawPublisherViewModel(IConnection connection, IPublishDestination publishDestination, BaseMessageInfo? receivedMessage = null)
public RawPublisherViewModel(IConnection connection, IPublishDestination publishDestination, IPayloadMacroProcessor payloadMacroProcessor, BaseMessageInfo? receivedMessage = null)
{
PayloadMacroProcessor = payloadMacroProcessor;
this.connection = connection;
this.publishDestination = publishDestination;
@ -242,6 +254,11 @@ namespace PettingZoo.UI.Tab.Publisher
}
}
var encodedPayload = Encoding.UTF8.GetBytes(
EnableMacros
? PayloadMacroProcessor.Apply(Payload)
: Payload
);
var headers = Headers.Where(h => h.IsValid()).ToDictionary(h => h.Key, h => h.Value);
var publishCorrelationId = NullIfEmpty(CorrelationId);
@ -250,7 +267,7 @@ namespace PettingZoo.UI.Tab.Publisher
connection.Publish(new PublishMessageInfo(
publishDestination.Exchange,
publishDestination.RoutingKey,
Encoding.UTF8.GetBytes(Payload),
encodedPayload,
new MessageProperties(headers)
{
AppId = NullIfEmpty(AppId),
@ -311,7 +328,7 @@ namespace PettingZoo.UI.Tab.Publisher
public class DesignTimeRawPublisherViewModel : RawPublisherViewModel
{
public DesignTimeRawPublisherViewModel() : base(null!, null!)
public DesignTimeRawPublisherViewModel() : base(null!, null!, null!)
{
PropertiesExpanded = true;

View File

@ -46,6 +46,7 @@
</Grid>
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelPayload}" />
<publisher:PayloadEditorControl Grid.Row="6" Grid.Column="1" Payload="{Binding Payload}" FixedJson="True" Height="350" x:Name="PayloadEditor"/>
<publisher:PayloadEditorControl Grid.Row="6" Grid.Column="1" Payload="{Binding Payload}" FixedJson="True" Height="350" x:Name="PayloadEditor"
EnableMacros="{Binding EnableMacros}" />
</controls:GridLayout>
</UserControl>

View File

@ -1,5 +1,6 @@
using System.Windows;
using System.Windows.Controls;
using PettingZoo.Core.Macros;
namespace PettingZoo.UI.Tab.Publisher
{
@ -15,6 +16,7 @@ namespace PettingZoo.UI.Tab.Publisher
InitializeComponent();
PayloadEditor.Validator = viewModel;
PayloadEditor.MacroProcessor = viewModel.PayloadMacroProcessor;
}

View File

@ -4,6 +4,7 @@ using System.Windows;
using System.Windows.Input;
using PettingZoo.Core.Connection;
using PettingZoo.Core.Generator;
using PettingZoo.Core.Macros;
using PettingZoo.Core.Validation;
using PettingZoo.WPF.ViewModel;
using IConnection = PettingZoo.Core.Connection.IConnection;
@ -20,6 +21,7 @@ namespace PettingZoo.UI.Tab.Publisher
private string correlationId = "";
private string payload = "";
private bool enableMacros;
private string className = "";
private string assemblyName = "";
private Window? tabHostWindow;
@ -67,9 +69,17 @@ namespace PettingZoo.UI.Tab.Publisher
}
public bool EnableMacros
{
get => enableMacros;
set => SetField(ref enableMacros, value);
}
public ICommand PublishCommand => publishCommand;
public ICommand BrowseClassCommand => browseClassCommand;
public IPayloadMacroProcessor PayloadMacroProcessor { get; }
public static bool IsTapetiMessage(ReceivedMessageInfo receivedMessage)
@ -99,8 +109,11 @@ namespace PettingZoo.UI.Tab.Publisher
}
public TapetiPublisherViewModel(IConnection connection, IPublishDestination publishDestination, IExampleGenerator exampleGenerator, ReceivedMessageInfo? receivedMessage = null)
public TapetiPublisherViewModel(IConnection connection, IPublishDestination publishDestination, IExampleGenerator exampleGenerator,
IPayloadMacroProcessor payloadMacroProcessor, ReceivedMessageInfo? receivedMessage = null)
{
PayloadMacroProcessor = payloadMacroProcessor;
this.connection = connection;
this.publishDestination = publishDestination;
this.exampleGenerator = exampleGenerator;
@ -154,13 +167,20 @@ namespace PettingZoo.UI.Tab.Publisher
return string.IsNullOrEmpty(value) ? null : value;
}
var encodedPayload = Encoding.UTF8.GetBytes(
EnableMacros
? PayloadMacroProcessor.Apply(Payload)
: Payload
);
var publishCorrelationId = NullIfEmpty(CorrelationId);
var replyTo = publishDestination.GetReplyTo(ref publishCorrelationId);
connection.Publish(new PublishMessageInfo(
publishDestination.Exchange,
publishDestination.RoutingKey,
Encoding.UTF8.GetBytes(Payload),
encodedPayload,
new MessageProperties(new Dictionary<string, string>
{
{ @"classType", $"{ClassName}:{AssemblyName}" }
@ -204,7 +224,7 @@ namespace PettingZoo.UI.Tab.Publisher
public class DesignTimeTapetiPublisherViewModel : TapetiPublisherViewModel
{
public DesignTimeTapetiPublisherViewModel() : base(null!, null!, null!)
public DesignTimeTapetiPublisherViewModel() : base(null!, null!, null!, null!)
{
AssemblyName = "Messaging.Example";
ClassName = "Messaging.Example.ExampleMessage";

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using PettingZoo.Core.Connection;
using PettingZoo.Core.ExportImport;
using PettingZoo.Core.Generator;
using PettingZoo.Core.Macros;
using PettingZoo.UI.Tab.Publisher;
using PettingZoo.UI.Tab.Subscriber;
using Serilog;
@ -15,18 +16,21 @@ namespace PettingZoo.UI.Tab
private readonly ITabHostProvider tabHostProvider;
private readonly IExampleGenerator exampleGenerator;
private readonly IExportImportFormatProvider exportImportFormatProvider;
private readonly IPayloadMacroProcessor payloadMacroProcessor;
// Not the cleanest way, but this factory itself can't be singleton without (justifyable) upsetting SimpleInjector
private static ISubscriber? replySubscriber;
private static ITab? replySubscriberTab;
public ViewTabFactory(ILogger logger, ITabHostProvider tabHostProvider, IExampleGenerator exampleGenerator, IExportImportFormatProvider exportImportFormatProvider)
public ViewTabFactory(ILogger logger, ITabHostProvider tabHostProvider, IExampleGenerator exampleGenerator, IExportImportFormatProvider exportImportFormatProvider,
IPayloadMacroProcessor payloadMacroProcessor)
{
this.logger = logger;
this.tabHostProvider = tabHostProvider;
this.exampleGenerator = exampleGenerator;
this.exportImportFormatProvider = exportImportFormatProvider;
this.payloadMacroProcessor = payloadMacroProcessor;
}
@ -59,7 +63,7 @@ namespace PettingZoo.UI.Tab
public void CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null)
{
var viewModel = new PublisherViewModel(this, connection, exampleGenerator, fromReceivedMessage);
var viewModel = new PublisherViewModel(this, connection, exampleGenerator, payloadMacroProcessor, fromReceivedMessage);
var tab = new ViewTab<PublisherView, PublisherViewModel>(
new PublisherView(viewModel),
viewModel,