Implemented logging
This commit is contained in:
parent
3766f72d4e
commit
b946bc32a6
|
|
@ -13,8 +13,8 @@ namespace Elsa {
|
|||
});
|
||||
}
|
||||
|
||||
static getSourceEndpointOptions(activityId: any, endpointName: any, hasExecuted: boolean, hasFaulted: boolean): any {
|
||||
const fill = hasFaulted ? '#d23c3c' : hasExecuted? '#6faa44' : '#7da7f2';
|
||||
static getSourceEndpointOptions(activityId: any, endpointName: any, hasExecuted: boolean, hasFaulted: boolean, isBlocking: boolean): any {
|
||||
const fill = isBlocking ? '#7da7f2' : hasFaulted ? '#d23c3c' : hasExecuted? '#6faa44' : '#7da7f2';
|
||||
const stroke = fill;
|
||||
return {
|
||||
endpoint: 'Dot',
|
||||
|
|
@ -29,19 +29,19 @@ namespace Elsa {
|
|||
connector: ['Flowchart', {stub: [40, 60], gap: 0, cornerRadius: 5, alwaysRespectStubs: true}],
|
||||
connectorStyle: {
|
||||
strokeWidth: 2,
|
||||
stroke: '#999999',
|
||||
stroke: !isBlocking && (hasFaulted || hasExecuted) ? fill : '#999999',
|
||||
joinstyle: 'round',
|
||||
outlineStroke: 'white',
|
||||
outlineWidth: 2
|
||||
outlineWidth: 1
|
||||
},
|
||||
hoverPaintStyle: {
|
||||
fill: stroke,
|
||||
stroke: fill
|
||||
},
|
||||
connectorHoverStyle: {
|
||||
connectorHoverStyle: isBlocking || hasFaulted || hasExecuted ? null : {
|
||||
strokeWidth: 3,
|
||||
stroke: stroke,
|
||||
outlineWidth: 5,
|
||||
outlineWidth: 1,
|
||||
outlineStroke: 'white'
|
||||
},
|
||||
connectorOverlays: [['Label', {location: [3, -1.5], cssClass: 'endpointSourceLabel'}]],
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ namespace Elsa {
|
|||
private readonly container: JQuery<HTMLElement>;
|
||||
private readonly canvasContainer: JQuery<HTMLElement>;
|
||||
private readonly isDefinition: boolean;
|
||||
private readonly executionLog: Array<LogEntry>;
|
||||
private readonly plumber: any;
|
||||
private dragStart: { left: number; top: number };
|
||||
private hasDragged: boolean;
|
||||
|
|
@ -22,7 +21,6 @@ namespace Elsa {
|
|||
this.container = $(containerElement);
|
||||
this.canvasContainer = this.container.find('.workflow-canvas');
|
||||
this.isDefinition = this.canvasContainer.data('workflow-is-definition');
|
||||
this.executionLog = this.canvasContainer.data('workflow-execution-log');
|
||||
this.plumber = WorkflowDesignerConfig.createJsPlumbInstance(this.canvasContainer[0]);
|
||||
this.initializeNodes();
|
||||
this.container.on('contextmenu', '.workflow-canvas', this.onCanvasContextMenu);
|
||||
|
|
@ -31,6 +29,10 @@ namespace Elsa {
|
|||
this.canvasContainer.on('click', '.activity .context-menu .dropdown-item', this.onActivityContextMenuItemClick);
|
||||
this.canvasContainer.on('click', '.canvas-context-menu .dropdown-item', this.onCanvasContextMenuItemClick);
|
||||
$(document).on('click', 'body', this.hideContextMenu);
|
||||
|
||||
this.canvasContainer.find('[data-toggle="popover"]').popover({
|
||||
container: '.workflow-canvas'
|
||||
})
|
||||
}
|
||||
|
||||
public getWorkflow = (): IWorkflow => {
|
||||
|
|
@ -247,7 +249,8 @@ namespace Elsa {
|
|||
for (let endpoint of endpoints) {
|
||||
const hasExecuted: boolean = $activityElement.data('activity-executed');
|
||||
const hasFaulted: boolean = $activityElement.data('activity-faulted');
|
||||
const sourceEndpointOptions: any = WorkflowDesignerConfig.getSourceEndpointOptions(activityId, endpoint.name, hasExecuted, hasFaulted);
|
||||
const isBlocking: boolean = $activityElement.data('activity-blocking');
|
||||
const sourceEndpointOptions: any = WorkflowDesignerConfig.getSourceEndpointOptions(activityId, endpoint.name, hasExecuted, hasFaulted, isBlocking);
|
||||
this.plumber.addEndpoint(activityElement, {
|
||||
connectorOverlays: [['Label', {
|
||||
label: endpoint.name,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
.activity {
|
||||
display: none;
|
||||
border: 1px solid #5a8fee;
|
||||
border: 1px solid #cccccc;
|
||||
box-shadow: 2px 2px 19px #aaa;
|
||||
-o-box-shadow: 2px 2px 9px #aaa;
|
||||
-webkit-box-shadow: 2px 2px 9px #aaa;
|
||||
|
|
@ -30,18 +30,49 @@
|
|||
-o-transition: -o-box-shadow 0.15s ease-in;
|
||||
transition: box-shadow 0.15s ease-in;
|
||||
|
||||
&.activity-executed {
|
||||
border: 1px solid #6faa44;
|
||||
.activity-status {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
bottom: 4px;
|
||||
cursor: pointer;
|
||||
i {
|
||||
|
||||
font-size: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
&.activity-start, &.activity-blocking {
|
||||
background-color: #f1f1f1;
|
||||
color: #3d3d3d;
|
||||
&.activity-definition {
|
||||
border: 1px solid #5a8fee;
|
||||
}
|
||||
|
||||
&.activity-executed {
|
||||
border: 1px solid #6faa44;
|
||||
|
||||
.activity-status {
|
||||
i {
|
||||
color: #6faa44;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.activity-blocking {
|
||||
border: 1px solid #5a8fee;
|
||||
|
||||
.activity-status {
|
||||
i {
|
||||
color: #5a8fee;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.activity-faulted {
|
||||
border: 1px solid #d23c3c;
|
||||
|
||||
.activity-status {
|
||||
i {
|
||||
color: #d23c3c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
|
|
@ -53,6 +84,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
.jtk-connector {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ namespace Elsa.Web.Components.Services
|
|||
shape.ActivityDescriptor = descriptor;
|
||||
shape.Activity = activity;
|
||||
shape.Designer = designerMetadata;
|
||||
shape.IsBlocking = false;
|
||||
shape.HasExecuted = false;
|
||||
shape.HasFaulted = false;
|
||||
shape.WorkflowIsDefinition = true;
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Models;
|
||||
using Elsa.Persistence;
|
||||
using Elsa.Web.Components.ViewModels;
|
||||
|
|
@ -35,9 +37,14 @@ namespace Elsa.Web.Components.ViewComponents
|
|||
private async Task<dynamic> BuildActivityShapeAsync(Workflow workflow, IActivity activity, CancellationToken cancellationToken)
|
||||
{
|
||||
var shape = (dynamic)await activityShapeFactory.BuildDesignShapeAsync(activity, cancellationToken);
|
||||
var logEntries = workflow.ExecutionLog.Where(x => x.ActivityId == activity.Id).OrderByDescending(x => x.Timestamp).ToList();
|
||||
var logEntries = workflow.ExecutionLog.Where(x => x.ActivityId == activity.Id).OrderBy(x => x.Timestamp).ToList();
|
||||
|
||||
shape.LogEntries = logEntries;
|
||||
shape.BlockingActivities = workflow.BlockingActivities;
|
||||
shape.HasExecuted = logEntries.Any();
|
||||
shape.HasFaulted = logEntries.Any(x => x.Faulted);
|
||||
shape.IsBlocking = workflow.BlockingActivities.Any(x => x.Id == activity.Id);
|
||||
shape.WorkflowIsDefinition = workflow.IsDefinition();
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
@using Elsa
|
||||
@using Elsa.Models
|
||||
@using Elsa.Web.Components.Models
|
||||
@using Microsoft.AspNetCore.Html
|
||||
@using Microsoft.Extensions.Localization
|
||||
@using Newtonsoft.Json
|
||||
@using Newtonsoft.Json.Serialization
|
||||
|
|
@ -14,28 +15,41 @@
|
|||
var activityJson = JsonConvert.SerializeObject(activity, serializerSettings);
|
||||
var activityEndpoints = JsonConvert.SerializeObject(endpoints, serializerSettings);
|
||||
var designer = (ActivityDesignerMetadata) Model.Designer;
|
||||
var logEntries = Model.LogEntries != null ? (ICollection<LogEntry>)Model.LogEntries : new List<LogEntry>();
|
||||
var logEntriesJson = JsonConvert.SerializeObject(logEntries, serializerSettings);
|
||||
var hasFaulted = logEntries.Any(x => x.Faulted);
|
||||
var hasExecuted = logEntries.Any();
|
||||
var hasFaulted = (bool)Model.HasFaulted;
|
||||
var hasExecuted = (bool)Model.HasExecuted;
|
||||
var isBlocking = (bool)Model.IsBlocking;
|
||||
var isDefinition = (bool)Model.WorkflowIsDefinition;
|
||||
var isInstance = !isDefinition;
|
||||
var cssClasses = new List<string> { "activity" };
|
||||
var left = designer.X;
|
||||
var top = designer.Y;
|
||||
|
||||
if (hasExecuted)
|
||||
if (isInstance)
|
||||
{
|
||||
cssClasses.Add("activity-executed");
|
||||
if (hasExecuted)
|
||||
{
|
||||
cssClasses.Add("activity-executed");
|
||||
}
|
||||
|
||||
if (hasFaulted)
|
||||
{
|
||||
cssClasses.Add("activity-faulted");
|
||||
}
|
||||
|
||||
if (isBlocking)
|
||||
{
|
||||
cssClasses.Add("activity-blocking");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cssClasses.Add("activity-definition");
|
||||
}
|
||||
|
||||
if (hasFaulted)
|
||||
{
|
||||
cssClasses.Add("activity-faulted");
|
||||
}
|
||||
|
||||
var cssClass = string.Join(" ", cssClasses);
|
||||
var activityClass = string.Join(" ", cssClasses);
|
||||
}
|
||||
<div
|
||||
class="@cssClass"
|
||||
class="@activityClass"
|
||||
style="left: @(left)px; top: @(top)px;"
|
||||
id="@($"activity-{id}")"
|
||||
title="@descriptor.DisplayText"
|
||||
|
|
@ -44,11 +58,30 @@
|
|||
data-activity-model="@activityJson"
|
||||
data-activity-endpoints="@activityEndpoints"
|
||||
data-activity-executed="@hasExecuted.ToString().ToLower()"
|
||||
data-activity-faulted="@hasFaulted.ToString().ToLower()"
|
||||
data-activity-log="@logEntriesJson">
|
||||
data-activity-blocking="@isBlocking.ToString().ToLower()"
|
||||
data-activity-faulted="@hasFaulted.ToString().ToLower()">
|
||||
@await DisplayAsync(Model.Content)
|
||||
<div class="dropdown-menu context-menu activity-context-menu">
|
||||
<a class="dropdown-item" href="#edit">Edit</a>
|
||||
<a class="dropdown-item" href="#delete">Delete</a>
|
||||
</div>
|
||||
|
||||
@if (isDefinition)
|
||||
{
|
||||
<div class="dropdown-menu context-menu activity-context-menu">
|
||||
<a class="dropdown-item" href="#edit">Edit</a>
|
||||
<a class="dropdown-item" href="#delete">Delete</a>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (isInstance)
|
||||
{
|
||||
var title = hasFaulted ? T["Faulted"] : isBlocking ? T["Awaiting Input"] : T["Executed"];
|
||||
var statusClass = hasFaulted ? "fas fa-exclamation-circle" : isBlocking ? "fas fa-hourglass-half" : "fas fa-check-circle";
|
||||
var logEntries = Model.LogEntries != null ? (ICollection<LogEntry>) Model.LogEntries : new List<LogEntry>();
|
||||
var logEntriesText = new HtmlString(string.Join("<br/>", logEntries.Select(x => $"{x.Timestamp}: {x.Message}")));
|
||||
|
||||
<div class="activity-status rounded-circle" tabindex="0" role="button" data-toggle="popover" data-trigger="focus" title="@title" data-content="@logEntriesText" data-html="true">
|
||||
@if (hasFaulted || isBlocking || hasExecuted)
|
||||
{
|
||||
<i class="@statusClass"></i>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
Loading…
Reference in a new issue