浏览代码

Added scriptable CreateEntity Action for events

Kenric Nugteren 6 月之前
父节点
当前提交
740e1fe59b
共有 2 个文件被更改,包括 111 次插入4 次删除
  1. 23 1
      prs.shared/Grids/EventEditor/Action Editors/CreateEntityActionEditor.cs
  2. 88 3
      prs.stores/Events/SaveEvent.cs

+ 23 - 1
prs.shared/Grids/EventEditor/Action Editors/CreateEntityActionEditor.cs

@@ -1,5 +1,6 @@
 using InABox.Core;
 using InABox.DynamicGrid;
+using InABox.Wpf;
 using InABox.WPF;
 using PRS.Shared.Events;
 using System;
@@ -19,6 +20,7 @@ public class CreateEntitySaveEventActionEditor<T> : IEventActionEditor<CreateEnt
 {
     private CreateEntitySaveEventAction<T> Action = null!;
     private PropertyInitializerGrid Grid = null!;
+    private Button ScriptButton = null!;
 
     public Type? SelectedType
     {
@@ -58,6 +60,7 @@ public class CreateEntitySaveEventActionEditor<T> : IEventActionEditor<CreateEnt
         grid.AddColumn(GridUnitType.Auto);
         grid.AddColumn(GridUnitType.Auto);
         grid.AddColumn(GridUnitType.Star);
+        grid.AddColumn(GridUnitType.Auto);
 
         grid.AddRow(GridUnitType.Auto);
         grid.AddRow(GridUnitType.Star);
@@ -81,6 +84,14 @@ public class CreateEntitySaveEventActionEditor<T> : IEventActionEditor<CreateEnt
         box.ItemsSource = entities;
         box.Bind(ComboBox.SelectedValueProperty, this, x => x.SelectedType);
 
+        ScriptButton = new Button
+        {
+            Padding = new(5),
+            Content = "Script"
+        };
+        ScriptButton.Bind(Button.IsEnabledProperty, this, x => x.SelectedType, converter: new FuncConverter(x => x is not null));
+        ScriptButton.Click += ScriptButton_Click;
+
         Grid = new()
         {
             EntityType = SelectedType,
@@ -92,7 +103,8 @@ public class CreateEntitySaveEventActionEditor<T> : IEventActionEditor<CreateEnt
         Grid.OnChanged += Grid_OnChanged;
 
         grid.AddChild(box, 0, 1);
-        grid.AddChild(Grid, 1, 0, colSpan: 3);
+        grid.AddChild(ScriptButton, 0, 3);
+        grid.AddChild(Grid, 1, 0, colSpan: 4);
 
         var dlg = new DynamicContentDialog(grid)
         {
@@ -111,6 +123,16 @@ public class CreateEntitySaveEventActionEditor<T> : IEventActionEditor<CreateEnt
         }
     }
 
+    private void ScriptButton_Click(object sender, RoutedEventArgs e)
+    {
+        var window = new ScriptEditorWindow(Action.Script ?? Action.DefaultScript(), scriptTitle: "Edit Create Entity Action");
+        if(window.ShowDialog() == true)
+        {
+            Action.Script = window.Script;
+            DoChanged();
+        }
+    }
+
     private void Grid_OnChanged(object? sender, EventArgs e)
     {
         DoChanged();

+ 88 - 3
prs.stores/Events/SaveEvent.cs

@@ -2,6 +2,7 @@
 using InABox.Core;
 using InABox.Database;
 using InABox.Scripting;
+using Inflector;
 using Newtonsoft.Json;
 using System;
 using System.Collections.Generic;
@@ -283,7 +284,10 @@ public class Module
 {
     public void RequiredColumns(Columns<" + typeof(T).Name + @"> columns)
     {
-        // Modify 'columns' as required.
+        // Modify 'columns' as required to get the required columns for the 'model.Entity'. If you don't provide these,
+        // the data you require in 'Execute' may not be present. Example:
+
+        // columns.Add(x => x.ID);
     }
 
     public bool Check(SaveEventDataModel<" + typeof(T).Name + @"> model)
@@ -369,7 +373,10 @@ public class Module
 
     public void RequiredColumns(Columns<" + typeof(T).Name + @"> columns)
     {
-        // Modify 'columns' as required.
+        // Modify 'columns' as required to get the required columns for the 'model.Entity'. If you don't provide these,
+        // the data you require in 'Execute' may not be present. Example:
+
+        // columns.Add(x => x.ID);
     }
 
     public bool Execute(SaveEventDataModel<" + typeof(T).Name + @"> model)
@@ -406,9 +413,79 @@ public class CreateEntitySaveEventAction<T> : IEventAction<SaveEvent<T>>
     [JsonIgnore]
     public List<PropertyInitializer> Initializers { get; set; } = new List<PropertyInitializer>();
 
+    private ScriptDocument? _scriptDocument;
+    private ScriptDocument? ScriptDocument
+    {
+        get
+        {
+            if(_scriptDocument is null && Script is not null)
+            {
+                _scriptDocument = new(Script);
+                _scriptDocument.Compile();
+            }
+            return _scriptDocument;
+        }
+    }
+
+    private string? _script;
+    public string? Script
+    {
+        get => _script;
+        set
+        {
+            if(_script != value)
+            {
+                _script = value;
+                _scriptDocument = null;
+            }
+        }
+    }
+
+    private IEnumerable<string> ScriptReferencedVariables
+    {
+        get
+        {
+            var method = ScriptDocument?.GetMethod(methodName: "RequiredColumns");
+            if(method is not null)
+            {
+                var cols = Columns.None<T>();
+                method.Invoke(ScriptDocument!.GetObject(), [cols]);
+                return cols.ColumnNames().Select(x => $"{typeof(T).Name}.{x}");
+            }
+            else
+            {
+                return [];
+            }
+        }
+    }
+
+    public string DefaultScript()
+    {
+        if (EntityType is null) return "Please select an entity type first.";
+
+        return @"using PRS.Shared.Events;
+
+public class Module
+{
+    public void RequiredColumns(Columns<" + typeof(T).Name + @"> columns)
+    {
+        // Modify 'columns' as required to get the required columns for the 'model.Entity'. If you don't provide these,
+        // the data you require in 'Execute' may not be present. Example:
+
+        // columns.Add(x => x.ID);
+    }
+
+    public void Execute(SaveEventDataModel<" + typeof(T).Name + @"> model, " + EntityType.Name + " new" + EntityType.Name + @")
+    {
+        // Modify new" + EntityType.Name + @" as you wish, using model.Entity to get the required data. This method runs after
+        // the property initializers (in the previous screen) for the Create Entity action have run.
+    }
+}";
+    }
+
     public string Description => $"Create New {EntityType?.Name ?? "Entity"}";
 
-    public IEnumerable<string> ReferencedVariables => Initializers.SelectMany(x => x.ReferencedVariables);
+    public IEnumerable<string> ReferencedVariables => Initializers.SelectMany(x => x.ReferencedVariables).Concat(ScriptReferencedVariables);
 
     public object? Execute(IEventDataModel dataModel)
     {
@@ -421,6 +498,14 @@ public class CreateEntitySaveEventAction<T> : IEventAction<SaveEvent<T>>
         {
             initializer.Execute(entity, dataModel);
         }
+
+        if(ScriptDocument is not null)
+        {
+            var model = dataModel.RootModel<SaveEventDataModel<T>>();
+
+            ScriptDocument.Execute(methodname: "Execute", parameters: [model, entity]);
+        }
+
         DbFactory.FindStore(EntityType, Guid.Empty, "", default, "", Logger.Main).Save(entity, "");
         return entity;
     }