Open zHaytam opened 1 year ago
@zHaytam hello, can we somehow turn it off untill it gets better performance wise ? when i try to move a node it lags so hard
thanks and great work !
Are you using Server Side Blazor? Moving a node doesn't use any javascript
No, im using blazor wasm .net 6 The early versions has no problmes but the latest one does become laggy ,much laggy
Im using custom nodes btw but they are simple nodes with 2 ports only
That's weird. What version are you using?
Latest version
Latest stable version or prelease? 2.1.6 or 3.x
2.1.6
Is your project private? Would it be possible for me to have a look at it? If not, can you send me at least the code for the nodes and how you create the diagram so that I try to reproduce the issue?
Problems occurs when a link is created and attached then trying to move the node around in the canvas it become laggy
ProcessWorkFlowVisualizer.razor
`
</div>
<CascadingValue Value="DiagramManager">
<DiagramCanvas></DiagramCanvas>
</CascadingValue>
@* <CascadingValue Name="DiagramManager" Value="DiagramManager">
<DiagramCanvas>
<Widgets>
<Navigator Width="200" Height="150" DefaultStyle="true"></Navigator>
</Widgets>
</DiagramCanvas>
</CascadingValue> *@
<div style="position: absolute; top: 90%; left: 3%;">
<NotificationComponent @ref="UpperNotificationComponentRef.Ref" />
<NotificationComponent @ref="LowerNotificationComponentRef.Ref" />
</div>
</div>
@{
CreateNewProcessFlowDialog = @<GroupComponent Title="{New} {ProcessFlow}" Icon="code-branch">
<CascadingValue Name="Model" Value="Model">
<LocalizedNameComponent Width="12" />
<FilterableViewElement Width="12" TModel="ProcessWorkFlow" TProperty="ProcessType"
PropertySelector="a=>a.ProcessType" FetchDataAsync="GetProcessTypes" />
<button class="btn btn-sm btn-primary" @onclick="CreateNewProcessFlow">@Localizer["Ok"]</button>
</CascadingValue>
</GroupComponent>;
OpenProcessFlowDialog = @<GroupComponent Title="{Open} {ProcessFlow}" Icon="code-branch">
<CascadingValue Name="Model" Value="VisualizerState">
<FilterableViewElement Width="12" TModel="ProcessFlowVisualizerState" TProperty="ProcessType"
PropertySelector="a=>a.ProcessType" FetchDataAsync="GetProcessTypes" />
<FilterableViewElement Width="12" TModel="ProcessFlowVisualizerState" TProperty="ProcessWorkFlow" @ref="_filterableElement"
PropertySelector="a=>a.CurrentWorkFlow" FetchDataAsync="GetProcessFlows" />
<button class="btn btn-sm btn-primary" @onclick="OpenProcessFlow">@Localizer["Open"]</button>
</CascadingValue>
</GroupComponent>;
}
` ProcessWorkFlowVisualizer.razor.cs
public class ProcessFlowVisualizerState : BaseDocument
{
private ProcessType _type;
public bool HasUnsavedChanges { get; set; }
public bool HasOpenedWorkFlow { get; set; }
public bool HasSelectedDeletableComponent { get; set; }
public string SelectedComponent { get; set; }
public int SelectedProcessFlowIndex { get; set; } = -1;
public ICollection<ProcessWorkFlow> Flows { get; set; }
public ProcessType ProcessType { get => _type; set => SetField(ref _type, value); }
public ProcessWorkFlow CurrentWorkFlow { get; set; }
public override string ID => "_visualizerState";
}
[Route("system/process/processFlow")]
public partial class ProcessWorkFlowVisualizer : ViewModelComponentBase<ProcessWorkFlow, ProcessWorkFlowVisualizer>
, IDisposable
{
FilterableViewElement<ProcessFlowVisualizerState, ProcessWorkFlow> _filterableElement;
private Diagram DiagramManager { get; set; }
ProcessFlowVisualizerState VisualizerState { get; set; } = new ProcessFlowVisualizerState();
//VisualSystemNode _tempSystemNodeDto;
//VisualTimeNode _tempTimerNodeDto;
//VisualProcessStateNode _tempProcessState;
RenderFragment SystemNodeDialog;
RenderFragment TransferNodeDialog;
RenderFragment PrintingNodeDialog;
RenderFragment TimerNodeDialog;
RenderFragment ProcessStateNodeDialog;
RenderFragment ProcessWorkFlowNodeDialog;
RenderFragment ConditionNodeDialog;
RenderFragment CreateNewProcessFlowDialog;
RenderFragment OpenProcessFlowDialog;
Func<Task> OnSystemNodeOkClick;
Func<Task> OnPrintingNodeOkClick;
Func<Task> OnTransferNodeOkClick;
Func<Task> OnTimerNodeOkClick;
Func<Task> OnProcessStateNodeOkClick;
Func<Task> OnProcessWorkFlowNodeOkClick;
Func<Task> OnNoClick;
public ProcessType SelectedProcessType { get; set; }
[Inject] IProcessModelsProvider ProcessModelsProvider { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
SetDiagramManager();
VisualizerState.PropertyChanged += (a, b) =>
{
if (b.PropertyName == "ProcessType")
_filterableElement?.GetData();
};
}
void SetDiagramManager()
{
var options = new DiagramOptions
{
DeleteKey = "Delete", // What key deletes the selected nodes/links
Zoom = new DiagramZoomOptions(){Inverse = true, }, // Whether to inverse the direction of the zoom when using the wheel
//Links= new DiagramLinkOptions() { DefaultLinkType = LinkType.Curved, },
// DefaultLinkType = LinkType.Curved,
DefaultNodeComponent = null, // Default component for nodes,
AllowMultiSelection = false, // Whether to allow multi selection using CTRL
// GroupingEnabled = true,
GridSize = 30,
Links = new DiagramLinkOptions
{
DefaultRouter = Routers.Orthogonal,
DefaultPathGenerator = PathGenerators.Straight,
DefaultLinkComponent = null,
// DefaultColor = "blue",
// DefaultSelectedColor = "red"
},
};
DiagramManager = new Diagram(options);
// DiagramManager = new DiagramManager(options);
// DiagramManager.LinkAdded += OnLinkAdded;
// DiagramManager.LinkAttached += OnLinkAttached;
// DiagramManager.LinkRemoved += OnLinkRemoved;
// DiagramManager.NodeAdded += OnNodeAdded;
// DiagramManager.NodeRemoved += OnNodeRemoved;
DiagramManager.Links.Added += OnLinkAdded;
DiagramManager.Links.Removed += OnLinkRemoved;
DiagramManager.Nodes.Added += OnNodeAdded;
DiagramManager.Nodes.Removed += OnNodeRemoved;
DiagramManager.RegisterModelComponent<VisualEntryNode, StartNodeComponent>();
DiagramManager.RegisterModelComponent<VisualTransferNode, TransferNodeComponent>();
DiagramManager.RegisterModelComponent<VisualProcessStateNode, ProcessStateComponent>();
DiagramManager.RegisterModelComponent<VisualPrintingNode, PrintingNodeComponent>();
DiagramManager.RegisterModelComponent<VisualSystemNode, SystemNodeComponent>();
DiagramManager.RegisterModelComponent<VisualTimeNode, TimerNodeComponent>();
DiagramManager.RegisterModelComponent<VisualConditionNode, ConditionNodeComponent>();
DiagramManager.RegisterModelComponent<VisualProcessWorkFlowNode, ProcessWorkFlowNodeComponent>();
//_tempSystemNodeDto = new VisualSystemNode();
//_tempTimerNodeDto = new VisualTimeNode();
//_tempProcessState = new VisualProcessStateNode();
OnSystemNodeOkClick = UpdateSystemNode;
OnTimerNodeOkClick = UpdateTimerNode;
OnProcessStateNodeOkClick = UpdateProcessStateNode;
OnProcessWorkFlowNodeOkClick = UpdateProcessWorkFlowNode;
OnNoClick = CancelUpdatingNode;
}
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
}
async Task<ReadOnlyObservableCollection<ProcessType>> GetProcessTypes(ProcessType type)
{
return new ReadOnlyObservableCollection<ProcessType>(new ObservableCollection<ProcessType>(ProcessModelsProvider.ProcessTypes));
}
async Task<ReadOnlyObservableCollection<ProcessWorkFlow>> GetProcessFlows(ProcessWorkFlow flow)
{
if (VisualizerState.ProcessType != null)
{
var _stages = MongoQuery.AsQuerying<ProcessWorkFlow>()
//.Match(a => a.ProcessTypeRef == VisualizerState.ProcessType.Id)
.Unwind(a => a.Nodes)
.LookUp(a => a.GroupsRefs, a => a.Id, a => a.Groups)
.Windup()
.Stages;
var _response = await Repository.Get(new MongoPaging<ProcessWorkFlow>() { Stages = _stages });
if (_response.Status == ResponseStatus.OK)
{
_processWorkFlows = _response.Result.ToList();
return new ReadOnlyObservableCollection<ProcessWorkFlow>
(new ObservableCollection<ProcessWorkFlow>(_processWorkFlows.Where(a => a.ProcessTypeRef == VisualizerState.ProcessType.Id)));
}
}
return new ReadOnlyObservableCollection<ProcessWorkFlow>(new ObservableCollection<ProcessWorkFlow>());
}
List<ProcessWorkFlow> _processWorkFlows = new();
void OpenProcessFlow()
{
isOpening = true;
List<BaseNode> nodeModels = new List<BaseNode>();
Dictionary<PortModel, PortModel[]> Links = new Dictionary<PortModel, PortModel[]>();
VisualizerState.CurrentWorkFlow.Nodes
.ForEach(n =>
{
if (n is EntryNode)
{
var k = n as EntryNode; //new EntryNode(n);
k.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
nodeModels.Add(new VisualEntryNode(k) { OnClick = OnNodeClick });
}
else if (n is ProcessWorkFlowNode)
{
var k = n as ProcessWorkFlowNode; //new ProcessWorkFlowNode(new SelectableNode(n));
k.WorkFlow = _processWorkFlows.FirstOrDefault(a => a.Id == k.ProcessWorkFlowRef);
k.EntryNode = k.WorkFlow?.Nodes.FirstOrDefault(a => a.Id == k.EntryNodeRef) as SelectableNode;
k.ClosingNodes = k.WorkFlow?.Nodes.Where(a => k.ClosingNodesRefs.Contains(a.Id))
.Select(a => (ProcessStateNode)a)
.ToObservableCollection();
if (k.ClosingNodes == null)
k.ClosingNodes = new ObservableCollection<ProcessStateNode>();
k.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
k.ClosingNodes.CollectionChanged += (a, b) => OnNodePropertyChanged(a, new PropertyChangedEventArgs("ClosingNodes"));
nodeModels.Add(new VisualProcessWorkFlowNode(k) { OnClick = OnNodeClick });
}
else if (n is ProcessStateNode)
{
var k = n as ProcessStateNode;
k.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
nodeModels.Add(new VisualProcessStateNode(k) { OnClick = OnNodeClick });
}
else if (n is TransferNode)
{
var k = n as TransferNode;
k.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
try
{
k.ChildType = ProcessModelsProvider.ProcessTypes.First(a=>a.Id == k.ChildTypeRef);
}
catch (Exception ex)
{
}
nodeModels.Add(new VisualTransferNode(k) { OnClick = OnNodeClick });
}
else if (n is SystemNode)
{
var k = n as SystemNode;
k.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
nodeModels.Add(new VisualSystemNode(k) { OnClick = OnNodeClick });
}
else if (n is PrintingNode)
{
var k = n as PrintingNode;
k.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
nodeModels.Add(new VisualPrintingNode(k) { OnClick = OnNodeClick });
}
else if (n is TimeNode)
{
var k = n as TimeNode;
k.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
nodeModels.Add(new VisualTimeNode(k) { OnClick = OnNodeClick });
}
else if (n is ConditionNode)
{
var k = n as ConditionNode;
k.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
nodeModels.Add(new VisualConditionNode(k) { OnClick = OnNodeClick });
}
else
throw new NotImplementedException($"Visualizer node is not implmeneted for type:[{n.GetType().Name}]");
});
nodeModels.ForEach(n => DiagramManager.Nodes.Add(n));
foreach (BaseNode nodeModel in nodeModels)
{
nodeModels.Where(a => nodeModel.AbstractNode.NextNodesRefs.Any(c => c == a.AbstractNode.Id))
.Select(a => a.GetPort(PortAlignment.Left))
.ForEach(p => DiagramManager.Links.Add(new LinkModel(nodeModel.GetPort(PortAlignment.Right), p)));
}
// DiagramManager.AddNodes(nodeModels.ToArray());
// foreach (BaseNode nodeModel in nodeModels)
// {
// nodeModels.Where(a => nodeModel.AbstractNode.NextNodesRefs.Any(c => c == a.AbstractNode.Id))
// .Select(a => a.GetPort(PortAlignment.Left))
// .ForEach(p => DiagramManager.AddLink(nodeModel.GetPort(PortAlignment.Right), p));
// }
Model = VisualizerState.CurrentWorkFlow;
Model.ProcessType = VisualizerState.ProcessType;
Model.Nodes = nodeModels.Select(a => a.AbstractNode).ToList();
VisualizerState.HasOpenedWorkFlow = true;
VisualizerState.HasUnsavedChanges = true;
SlideFormRef.Ref.Hide();
isOpening = false;
}
private void OnNodePropertyChanged(object a, PropertyChangedEventArgs b)
{
if (b.PropertyName == "Groups")
(a as Node).GroupsRefs = (a as Node).Groups.Select(a => a.Id).ToList();
else if (b.PropertyName == "IsAutoTrigger")
{
if ((a as SelectableNode).IsAutoTrigger)
(a as SelectableNode).Onsets.Clear();
}
else if (a is SystemNode)
{ }
else if (a is PrintingNode)
{ }
else if (a is TimeNode)
{ }
else if(a is TransferNode)
{
// var _node = a as TransferNode;
// if(b.PropertyName == "ChildType")
// _node.ChildTypeRef = _node.ChildType.Id;
}
else if (a is ProcessWorkFlowNode)
{
var _node = a as ProcessWorkFlowNode;
if (b.PropertyName == "WorkFlow")
{
_node.ProcessWorkFlowRef = _node.WorkFlow?.Id;
_node.ChildProcessTypeRef = _node.WorkFlow?.ProcessTypeRef;
DiagramManager.Nodes.First(a => a.Id == _node.Id)
.AllLinks
.Where(a => a.TargetPort.Parent != null && a.TargetPort.Parent is VisualConditionNode)
.Select(l => l.TargetPort.Parent as VisualConditionNode)
.ForEach(n => {
n.Node.IsChildProcess = true;
n.Node.ChildProcessTypeRef = _node.ChildProcessTypeRef;
});
}
else if (b.PropertyName == "ClosingNodes")
{
_node.ClosingNodesRefs = _node.ClosingNodes?.Select(a => a.Id).ToList();
}
else if (b.PropertyName == "EntryNode")
{
_node.EntryNodeRef = _node.EntryNode?.Id;
}
else if (b.PropertyName == "NodeType")
{
if (_node.NodeType == ProcessWorkFlowType.StartAndContinue)
{
_node.ClosingNodes = null;
}
}
}
else if (a is ProcessStateNode)
{ }
}
void CreateNewProcessFlow()
{
ClearBoard();
SetupModel();
VisualizerState.HasOpenedWorkFlow = true;
VisualizerState.HasSelectedDeletableComponent = false;
VisualizerState.HasUnsavedChanges = true;
VisualizerState.SelectedComponent = null;
StateHasChanged();
SlideFormRef.Ref.Hide();
}
// private void OnGroupAdded(Blazor.Diagrams.Core.Models.Group obj)
// {
// }
public void OnNodeRemoved(NodeModel obj)
{
try
{
Model.Nodes.Remove(Model.Nodes.First(a => a.Id == obj.Id));
var _nodes = Model.Nodes.Where(a => a.NextNodesRefs.Any(a => a == obj.Id)).ToList();
foreach (var _node in _nodes)
{
_node.NextNodesRefs.Remove(obj.Id);
}
}
catch(Exception e) { Helper.DebugConsole(e.Message); }
}
public void OnNodeAdded(NodeModel obj)
{
}
// public void OnLinkRemoved(LinkModel obj)
// {
// try
// {
// if (obj.IsAttached)
// {
// Model.Nodes.First(a => a.Id == obj.SourcePort.Parent.Id)
// .NextNodesRefs.Remove(obj.TargetPort.Parent.Id);
// }
// if (obj.SourcePort.Parent is VisualProcessWorkFlowNode && obj.TargetPort.Parent is VisualConditionNode)
// {
// (obj.TargetPort.Parent as VisualConditionNode).Node.IsChildProcess = false;
// (obj.TargetPort.Parent as VisualConditionNode).Node.ChildProcessTypeRef = null;
// }
// }
// catch { }
// }
// private void OnLinkAttached(LinkModel obj)
// {
// if (obj.SourcePort.Alignment == PortAlignment.Left || obj.TargetPort.Alignment == PortAlignment.Right)
// {
// // DiagramManager.RemoveLink(obj);
// DiagramManager.Links.Remove(obj);
// return;
// }
// if (obj.SourcePort.Parent is VisualEntryNode
// && (!(obj.TargetPort.Parent is VisualProcessStateNode) && !(obj.TargetPort.Parent is VisualProcessWorkFlowNode)))
// {
// // DiagramManager.RemoveLink(obj);
// DiagramManager.Links.Remove(obj);
// return;
// }
// if(obj.SourcePort.Parent is VisualProcessWorkFlowNode && obj.TargetPort.Parent is VisualTransferNode)
// (obj.TargetPort.Parent as VisualTransferNode).Node.ChildType
// = ProcessModelsProvider.ProcessTypes.FirstOrDefault(a=>a.Id == (obj.SourcePort.Parent as VisualProcessWorkFlowNode).Node.ChildProcessTypeRef);
// if (obj.SourcePort.Parent is VisualProcessWorkFlowNode && obj.TargetPort.Parent is VisualConditionNode)
// {
// (obj.TargetPort.Parent as VisualConditionNode).Node.IsChildProcess = true;
// (obj.TargetPort.Parent as VisualConditionNode).Node.ChildProcessTypeRef
// = (obj.SourcePort.Parent as VisualProcessWorkFlowNode).Node.ChildProcessTypeRef;
// }
// Model.Nodes.First(a => a.Id == obj.SourcePort.Parent.Id)
// .NextNodesRefs.Add(obj.TargetPort.Parent.Id);
// }
// private void OnLinkAdded(LinkModel obj)
// {
// }
public void OnLinkRemoved(BaseLinkModel obj)
{
try
{
if (obj.IsAttached)
{
Model.Nodes.First(a => a.Id == obj.SourcePort.Parent.Id)
.NextNodesRefs.Remove(obj.TargetPort.Parent.Id);
}
if (obj.SourcePort.Parent is VisualProcessWorkFlowNode && obj.TargetPort.Parent is VisualConditionNode)
{
(obj.TargetPort.Parent as VisualConditionNode).Node.IsChildProcess = false;
(obj.TargetPort.Parent as VisualConditionNode).Node.ChildProcessTypeRef = null;
}
}
catch(Exception e) { Helper.DebugConsole(e.Message); }
}
bool isOpening = false;
void OnLinkAttached(BaseLinkModel obj,PortModel? source,PortModel? target)
{
if (obj.SourcePort.Alignment == PortAlignment.Left || obj.TargetPort.Alignment == PortAlignment.Right)
{
// DiagramManager.RemoveLink(obj);
DiagramManager.Links.Remove(obj);
return;
}
if (obj.SourcePort.Parent is VisualEntryNode
&& (!(obj.TargetPort.Parent is VisualProcessStateNode) && !(obj.TargetPort.Parent is VisualProcessWorkFlowNode)))
{
// DiagramManager.RemoveLink(obj);
DiagramManager.Links.Remove(obj);
return;
}
if(obj.SourcePort.Parent is VisualProcessWorkFlowNode && obj.TargetPort.Parent is VisualTransferNode)
(obj.TargetPort.Parent as VisualTransferNode).Node.ChildType
= ProcessModelsProvider.ProcessTypes.FirstOrDefault(a=>a.Id == (obj.SourcePort.Parent as VisualProcessWorkFlowNode).Node.ChildProcessTypeRef);
if (obj.SourcePort.Parent is VisualProcessWorkFlowNode && obj.TargetPort.Parent is VisualConditionNode)
{
(obj.TargetPort.Parent as VisualConditionNode).Node.IsChildProcess = true;
(obj.TargetPort.Parent as VisualConditionNode).Node.ChildProcessTypeRef
= (obj.SourcePort.Parent as VisualProcessWorkFlowNode).Node.ChildProcessTypeRef;
}
Model.Nodes.First(a => a.Id == obj.SourcePort.Parent.Id)
.NextNodesRefs.Add(obj.TargetPort.Parent.Id);
}
private void OnLinkAdded(BaseLinkModel obj)
{
obj.TargetPortChanged += (a,b,c) => OnLinkAttached(a,b,c);
}
private void NewStartNodeClicked()
{
double x = new Random().Next(1, 300), y = new Random().Next(1, 300);
var node = new VisualEntryNode(new Point(x, y));
// DiagramManager.AddNode(node);
DiagramManager.Nodes.Add(node);
node.Node.Id = node.Id;
node.Node.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
Model.Nodes.Add(node.Node);
}
private void NewProcessStateNodeClicked()
{
double x = new Random().Next(1, 300), y = new Random().Next(1, 300);
var node = new VisualProcessStateNode(new Point(x, y));
node.Node.Id = node.Id;
node.OnClick = OnNodeClick;
// DiagramManager.AddNode(node);
DiagramManager.Nodes.Add(node);
node.Node.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
Model.Nodes.Add(node.Node);
}
private void NewTimerNodeClicked()
{
double x = new Random().Next(1, 300), y = new Random().Next(1, 300);
var node = new VisualTimeNode(new Point(x, y));
// DiagramManager.AddNode(node);
DiagramManager.Nodes.Add(node);
node.OnClick = OnNodeClick;
node.Node.Id = node.Id;
node.Node.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
Model.Nodes.Add(node.Node);
}
private void NewSystemNodeClicked()
{
double x = new Random().Next(1, 300), y = new Random().Next(1, 300);
var node = new VisualSystemNode(new Point(x, y));
// DiagramManager.AddNode(node);
DiagramManager.Nodes.Add(node);
node.Node.Id = node.Id;
node.OnClick = OnNodeClick;
node.Node.ProcessType = ProcessModelsProvider.CreateProcess(VisualizerState.CurrentWorkFlow.ProcessType.Id, "").GetType();
node.Node.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
Model.Nodes.Add(node.Node);
}
void NewWorkFlowNodeClicked()
{
Helper.DebugConsole("New Workflow Node");
double x = new Random().Next(1, 300), y = new Random().Next(1, 300);
var node = new VisualProcessWorkFlowNode(new Point(x, y));
// DiagramManager.AddNode(node);
DiagramManager.Nodes.Add(node);
node.Node.Id = node.Id;
node.OnClick = OnNodeClick;
node.Node.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
node.Node.ClosingNodes.CollectionChanged += (a, b) => OnNodePropertyChanged(a, new PropertyChangedEventArgs("ClosingNodes"));
Model.Nodes.Add(node.Node);
}
void NewConditionNodeClicked()
{
Helper.DebugConsole("New Condition Node");
double x = new Random().Next(1, 300), y = new Random().Next(1, 300);
var node = new VisualConditionNode(new Point(x, y));
// DiagramManager.AddNode(node);
DiagramManager.Nodes.Add(node);
node.Node.Id = node.Id;
node.OnClick = OnNodeClick;
node.Node.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
Model.Nodes.Add(node.Node);
}
void NewPrintingNodeClicked()
{
Helper.DebugConsole("New Printing Node");
double x = new Random().Next(1, 300), y = new Random().Next(1, 300);
var node = new VisualPrintingNode(new Point(x, y));
// DiagramManager.AddNode(node);
DiagramManager.Nodes.Add(node);
node.Node.Id = node.Id;
node.OnClick = OnNodeClick;
node.Node.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
Model.Nodes.Add(node.Node);
}
void NewTransferNodeClicked()
{
Helper.DebugConsole("New Transfer Node");
double x = new Random().Next(1, 300), y = new Random().Next(1, 300);
var node = new VisualTransferNode(new Point(x, y));
// DiagramManager.AddNode(node);
DiagramManager.Nodes.Add(node);
node.Node.Id = node.Id;
node.OnClick = OnNodeClick;
node.Node.PropertyChanged += (a, b) => OnNodePropertyChanged(a, b);
Model.Nodes.Add(node.Node);
}
string _nodeRef;
async Task UpdateProcessWorkFlowNode()
{
}
async Task UpdateSystemNode()
{
var _dNode = (VisualSystemNode)DiagramManager.Nodes.FirstOrDefault(a => a.Id == _nodeRef);
SlideFormRef.Ref.Hide();
}
async Task UpdateTimerNode()
{
var _dNode = (VisualTimeNode)DiagramManager.Nodes.FirstOrDefault(a => a.Id == _nodeRef);
SlideFormRef.Ref.Hide();
}
async Task UpdateProcessStateNode()
{
var _dNode = (VisualProcessStateNode)DiagramManager.Nodes.FirstOrDefault(a => a.Id == _nodeRef);
SlideFormRef.Ref.Hide();
}
async Task CancelUpdatingNode()
{
SlideFormRef.Ref.Hide();
}
void OnNodeClick(string id)
{
var _node = Model.Nodes.FirstOrDefault(a => a.Id == id);
SlideFormRef.Ref.SetWidthPercentage(50);
_nodeRef = id;
if (_node is SystemNode)
{
SystemNodeDialog = builder =>
{
builder.OpenComponent<SystemNodeDialog>(0);
builder.AddAttribute(0, "SystemNode", (SystemNode)_node);
builder.AddAttribute(0, "OnOkClick", OnSystemNodeOkClick);
builder.AddAttribute(0, "OnNoClick", OnNoClick);
builder.CloseComponent();
};
SlideFormRef.Ref.AttachElementByRenderFragment(SystemNodeDialog);
SlideFormRef.Ref.Show();
}
else if (_node is TransferNode)
{
TransferNodeDialog = builder =>
{
builder.OpenComponent<TransferNodeDialog>(0);
builder.AddAttribute(0, "TransferNode", (TransferNode)_node);
builder.AddAttribute(0, "ProcessTypeId",Model.ProcessType.Id);
builder.AddAttribute(0, "OnOkClick", OnTransferNodeOkClick);
builder.AddAttribute(0, "OnNoClick", OnNoClick);
builder.CloseComponent();
};
SlideFormRef.Ref.AttachElementByRenderFragment(TransferNodeDialog);
SlideFormRef.Ref.Show();
}
else if (_node is PrintingNode)
{
PrintingNodeDialog = builder =>
{
builder.OpenComponent<PrintingNodeDialog>(0);
builder.AddAttribute(0, "PrintingNode", (PrintingNode)_node);
builder.AddAttribute(0, "OnOkClick", OnPrintingNodeOkClick);
builder.AddAttribute(0, "OnNoClick", OnNoClick);
builder.CloseComponent();
};
SlideFormRef.Ref.AttachElementByRenderFragment(PrintingNodeDialog);
SlideFormRef.Ref.Show();
}
else if (_node is TimeNode)
{
TimerNodeDialog = builder =>
{ // one time intilizing and add Set(node) method for NodeDialog.razor and only use Set(node) rather than re-initiate
builder.OpenComponent<TimerNodeDialog>(0);
builder.AddAttribute(0, "TimeNode", (TimeNode)_node);
builder.AddAttribute(0, "OnOkClick", OnTimerNodeOkClick);
builder.AddAttribute(0, "OnNoClick", OnNoClick);
builder.AddAttribute(0, "Paths", new Dictionary<string, string>(new[] {
new KeyValuePair<string,string>("Path1","Prop1")
,new KeyValuePair<string,string>("Path2","Prop2")}));
builder.CloseComponent();
};
SlideFormRef.Ref.AttachElementByRenderFragment(TimerNodeDialog);
SlideFormRef.Ref.Show();
}
else if (_node is ConditionNode)
{
var _condNode = (ConditionNode)_node;
ConditionNodeDialog = builder =>
{ // one time intilizing and add Set(node) method for NodeDialog.razor and only use Set(node) rather than re-initiate
builder.OpenComponent<ConditionNodeDialog>(0);
builder.AddAttribute(0, "ConditionNode", _condNode);
builder.AddAttribute(0, "ProcessTypeId", _condNode.ChildProcessTypeRef ?? Model.ProcessType.Id);
builder.AddAttribute(0, "OnNoClick", OnNoClick);
builder.CloseComponent();
};
SlideFormRef.Ref.AttachElementByRenderFragment(ConditionNodeDialog);
SlideFormRef.Ref.Show();
}
else if (_node is ProcessWorkFlowNode)
{
ProcessWorkFlowNodeDialog = builder =>
{
builder.OpenComponent<ProcessWorkFlowNodeDialog>(0);
builder.AddAttribute(0, "ProcessWorkFlowNode", (ProcessWorkFlowNode)_node);
builder.AddAttribute(0, "OnOkClick", OnProcessStateNodeOkClick);
builder.AddAttribute(0, "OnNoClick", OnNoClick);
builder.AddAttribute(0, "ProcessTypeId", Model.ProcessType.Id);
builder.CloseComponent();
};
SlideFormRef.Ref.AttachElementByRenderFragment(ProcessWorkFlowNodeDialog);
SlideFormRef.Ref.Show();
}
else if (_node is ProcessStateNode)
{
ProcessStateNodeDialog = builder =>
{
builder.OpenComponent<ProcessStateDialog>(0);
builder.AddAttribute(0, "ProcessStateNode", (ProcessStateNode)_node);
builder.AddAttribute(0, "OnOkClick", OnProcessStateNodeOkClick);
builder.AddAttribute(0, "OnNoClick", OnNoClick);
builder.AddAttribute(0, "ProcessTypeId", Model.ProcessType.Id);
builder.CloseComponent();
};
SlideFormRef.Ref.AttachElementByRenderFragment(ProcessStateNodeDialog);
SlideFormRef.Ref.Show();
}
}
void InfoClicked()
{ }
async void SavedClicked()
{
if (string.IsNullOrWhiteSpace(Model.LocalizedName))
{
JSRuntime.ShowToast(Localizer["Current WorkFlow has no name"], StatusType.error);
return;
}
if (DiagramManager.Nodes.All(a => !(a is VisualEntryNode)))
{
JSRuntime.ShowToast(Localizer["At least one entry node with link to state node"], StatusType.error);
return;
}
if (DiagramManager.Nodes.Where(a => a is VisualEntryNode).Any(a => a.AllLinks.Count() == 0))
{
JSRuntime.ShowToast(Localizer["Entry nodes must be with links to state node"], StatusType.error);
return;
}
Model.Nodes.ForEach(n => n.Point = DiagramManager.Nodes.Where(a => a.Id == n.Id).Select(a => new NodePoint() { X = a.Position.X, Y = a.Position.Y }).First());
Model.ProcessTypeRef = Model.ProcessType.Id;
Model.Nodes.ForEach(n => n.OnUpdating());
await CreateOrUpdateAsync();
ClearBoard();
VisualizerState.HasOpenedWorkFlow = false;
VisualizerState.HasSelectedDeletableComponent = false;
VisualizerState.HasUnsavedChanges = false;
VisualizerState.SelectedComponent = null;
StateHasChanged();
}
private void ClearBoard()
{
var _enumerator = DiagramManager.Nodes.GetEnumerator();
var _nodes = new List<NodeModel>();
while (_enumerator.MoveNext())
{
_nodes.Add(_enumerator.Current);
}
for (int i = _nodes.Count - 1; i >= 0; i--)
{
// DiagramManager.RemoveNode(_nodes[i], false);
DiagramManager.Nodes.Remove(_nodes[i]);
}
DiagramManager.Refresh();
}
void NewClicked()
{
Model = new ProcessWorkFlow();
SlideFormRef.Ref.AttachElementByRenderFragment(CreateNewProcessFlowDialog);
SlideFormRef.Ref.Show();
}
void OpenClicked()
{
SlideFormRef.Ref.AttachElementByRenderFragment(OpenProcessFlowDialog);
SlideFormRef.Ref.Show();
}
public void Dispose()
{
if (DiagramManager != null)
{
// DiagramManager.LinkAdded -= OnLinkAdded;
// DiagramManager.LinkAttached -= OnLinkAttached;
// DiagramManager.LinkRemoved -= OnLinkRemoved;
// DiagramManager.NodeAdded -= OnNodeAdded;
// DiagramManager.NodeRemoved -= OnNodeRemoved;
DiagramManager.Links.Added -= OnLinkAdded;
DiagramManager.Links.Removed -= OnLinkRemoved;
DiagramManager.Nodes.Added -= OnNodeAdded;
DiagramManager.Nodes.Removed -= OnNodeRemoved;
}
}
}
`
@zHaytam
Is the project currently paused? There have been no updates for a while and you said that version 3.0 would come out of beta in December.
Cheers!
@zHaytam
Is the project currently paused? There have been no updates for a while and you said that version 3.0 would come out of beta in December.
Cheers!
Health issues again + a job change, I didn't have much time these weeks until this week. I'm still writing the documentation website for 3.0
Other improvements are to be found on the way.