* ignoring start button click in Test mode

* #1651: added word-break to endpoint URL

* #1651: refresh test panel on workflow execute, if activity is already selected

* removed clipboard permission checks that failed to build

Seems like an old ongoing issue with TypeScript: https://github.com/microsoft/TypeScript/issues/33923

* #1651: fixed flyout panel position

* #1651: flyout panel button position fix

* #1651: fixed javascript evaluation exception being swallowed

* #1651: added copy button to http entry endpoint url

* #1651: test panel refactoring, use schema button for SendHttpRequest

* #1651: add node is not clickable in test mode

* fixed "can't access property "contains", this.contextMenuWidget is undefined"

* added couple safeguard checks to context menu

* reversed incorrect update

* #1651: added z-index to toaster to move it to front

* removed unnecessary empty line
This commit is contained in:
Konstantins Vedenins 2021-10-21 12:00:17 +03:00 committed by GitHub
parent e116ca8624
commit bccb32b003
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 46 additions and 44 deletions

View file

@ -328,6 +328,7 @@ namespace Elsa.Services.Workflows
_logger.LogWarning(e, "Failed to run activity {ActivityId} of workflow {WorkflowInstanceId}", activity.Id, activityExecutionContext.WorkflowInstance.Id);
activityExecutionContext.Fault(e);
await _mediator.Publish(new ActivityFaulted(e, activityExecutionContext, activity), cancellationToken);
await _mediator.Publish(new ActivityExecutionResultFailed(e, activityExecutionContext), cancellationToken);
}
return null;

View file

@ -31,7 +31,8 @@ export class ElsaContextMenu {
}
closeContextMenu() {
leave(this.contextMenu);
if (!!this.contextMenu)
leave(this.contextMenu);
}
toggleMenu() {

View file

@ -187,14 +187,11 @@ export class ElsaWorkflowDesigner {
}
async copyActivitiesToClipboard() {
this.checkClipboardPermissions();
await navigator.clipboard.writeText(JSON.stringify(this.selectedActivities));
await eventBus.emit(EventTypes.ClipboardCopied, this);
}
async pasteActivitiesFromClipboard() {
this.checkClipboardPermissions();
let copiedActivities: Array<ActivityModel> = [];
await navigator.clipboard.readText().then(data => {
@ -233,13 +230,6 @@ export class ElsaWorkflowDesigner {
this.parentActivityOutcome = null;
}
checkClipboardPermissions() {
navigator.permissions.query({name: "clipboard-read"}).then((result) => {
if (result.state == 'denied')
eventBus.emit(EventTypes.ClipboardPermissionDenied, this);
});
}
connectedCallback() {
eventBus.on(EventTypes.ActivityPicked, this.onActivityPicked);
eventBus.on(EventTypes.UpdateActivity, this.onUpdateActivity);
@ -715,8 +705,8 @@ export class ElsaWorkflowDesigner {
d3.select(node.elem).select('svg').classed('elsa-text-green-400', true).classed('elsa-text-gray-400', false).classed('hover:elsa-text-blue-500', false);
return;
}
await this.showActivityPicker();
if (this.mode !== WorkflowDesignerMode.Test) await this.showActivityPicker();
})
.on("mouseover", e => {
if (e.shiftKey)
@ -737,6 +727,8 @@ export class ElsaWorkflowDesigner {
root.selectAll('.node.start').each((n: any) => {
const node = this.graph.node(n) as any;
d3.select(node.elem).on('click', async e => {
if (this.mode == WorkflowDesignerMode.Test) return;
await this.showActivityPicker();
});
});

View file

@ -40,7 +40,7 @@ export class ElsaMultiExpressionEditor {
onWindowClicked(event: Event){
const target = event.target as HTMLElement;
if (!this.contextMenuWidget.contains(target))
if (!this.contextMenuWidget || !this.contextMenuWidget.contains(target))
this.closeContextMenu();
}
@ -53,7 +53,8 @@ export class ElsaMultiExpressionEditor {
}
closeContextMenu() {
leave(this.contextMenu);
if (!!this.contextMenu)
leave(this.contextMenu);
}
selectDefaultEditor(e: Event) {

View file

@ -593,9 +593,9 @@ export class ElsaWorkflowDefinitionEditorScreen {
onActivityDeselected={e => this.onActivityDeselected(e)}
class="elsa-flex-1"
ref={el => this.designer = el}/>
{this.renderPanel()}
{this.renderWorkflowSettingsButton()}
{this.renderWorkflowHelpButton()}
{this.renderPanel()}
{this.renderActivityContextMenu()}
{this.renderConnectionContextMenu()}
<elsa-workflow-settings-modal workflowDefinition={this.workflowDefinition}/>

View file

@ -60,6 +60,10 @@ export class ElsaWorkflowTestPanel {
if (message.workflowStatus == 'Executed') {
this.workflowStarted = false;
}
if (!this.message && message.activityId == this.workflowTestActivityId){
this.message = message;
}
});
this.hubConnection.start()
@ -110,6 +114,28 @@ export class ElsaWorkflowTestPanel {
const workflowStatus = this.workflowTestActivityMessages.last().workflowStatus;
const t = (x, params?) => this.i18next.t(x, params);
const renderEndpointUrl = () => {
if (!message.activityData || !message.activityData["Path"]) return undefined;
const endpointUrl = this.serverUrl + '/workflows' + message.activityData["Path"].value + '?correlation=' + message.correlationId;
return (
<div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">
<span class="elsa-mr-1">{t('EntryEndpoint')}</span>
<elsa-copy-button value={endpointUrl} />
</dt>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-900">
<span class="elsa-break-all font-mono" onClick={e => clip(e.currentTarget)}>{endpointUrl}</span>
</dt>
</div>
</div>
);
};
return (
<dl class="elsa-border-b elsa-border-gray-200 elsa-divide-y elsa-divide-gray-200">
@ -117,20 +143,7 @@ export class ElsaWorkflowTestPanel {
<dt class="elsa-text-gray-500">{t('Status')}</dt>
<dd class="elsa-text-gray-900">{workflowStatus}</dd>
</div>
{!!message.activityData["Path"] ?
<div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('EntryEndpoint')}</dt>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-900">
<pre onClick={e => clip(e.currentTarget)}>{this.serverUrl + '/workflows' + message.activityData["Path"].value + '?correlation=' + message.correlationId}</pre>
</dt>
</div>
</div>
:
undefined
}
{renderEndpointUrl()}
</dl>
);
}

View file

@ -24,17 +24,7 @@ export class ElsaCopyButton {
onCopyClick = async (e) => {
e.stopPropagation();
this.checkClipboardPermissions();
await navigator.clipboard.writeText(this.value);
await eventBus.emit(EventTypes.ClipboardCopied, this, undefined, 'Data copied to clipboard.');
}
checkClipboardPermissions = () => {
navigator.permissions.query({name: 'clipboard-read'}).then((result) => {
if (result.state == 'denied')
eventBus.emit(EventTypes.ClipboardPermissionDenied, this);
});
}
}

View file

@ -51,7 +51,7 @@ export class ElsaFlyoutPanel {
<div class="elsa-absolute elsa-inset-0 elsa-overflow-hidden">
<div class="elsa-absolute elsa-inset-0" aria-hidden="true"/>
<div
class="elsa-fixed elsa-inset-y-0 elsa-top-18 elsa-right-2 elsa-top-2 elsa-bottom-2 max-elsa-w-full elsa-flex">
class="elsa-fixed elsa-top-20 elsa-inset-y-0 elsa-right-2 elsa-bottom-2 max-elsa-w-full elsa-flex">
<div
ref={el => this.el = el}
data-transition-enter="elsa-transform elsa-transition elsa-ease-in-out elsa-duration-300 sm:elsa-duration-700"
@ -63,7 +63,7 @@ export class ElsaFlyoutPanel {
class="elsa-w-screen elsa-max-w-lg elsa-h-full ">
<button type="button"
onClick={this.toggle}
class="workflow-settings-button elsa-absolute elsa-top-4 elsa-left-2 elsa-inline-flex elsa-items-center elsa-p-2 elsa-rounded-full elsa-border elsa-border-transparent elsa-bg-white shadow elsa-text-gray-400 hover:elsa-text-blue-500 focus:elsa-text-blue-500 hover:elsa-ring-2 hover:elsa-ring-offset-2 hover:elsa-ring-blue-500 focus:elsa-outline-none focus:elsa-ring-2 focus:elsa-ring-offset-2 focus:elsa-ring-blue-500 elsa-z-10">
class="workflow-settings-button elsa-absolute elsa-left-2 elsa-inline-flex elsa-items-center elsa-p-2 elsa-rounded-full elsa-border elsa-border-transparent elsa-bg-white shadow elsa-text-gray-400 hover:elsa-text-blue-500 focus:elsa-text-blue-500 hover:elsa-ring-2 hover:elsa-ring-offset-2 hover:elsa-ring-blue-500 focus:elsa-outline-none focus:elsa-ring-2 focus:elsa-ring-offset-2 focus:elsa-ring-blue-500 elsa-z-10">
<svg xmlns="http://www.w3.org/2000/svg" class="elsa-h-8 elsa-w-8" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"

View file

@ -42,7 +42,7 @@ export class ElsaToastNotification {
renderToast() {
return (
<Host class={{'hidden': !this.isVisible, 'elsa-block': true}}>
<div class="elsa-fixed elsa-inset-0 elsa-flex elsa-items-end elsa-justify-center elsa-px-4 elsa-py-6 elsa-pointer-events-none sm:elsa-p-6 sm:elsa-items-start sm:elsa-justify-end">
<div class="elsa-fixed elsa-inset-0 elsa-z-20 elsa-flex elsa-items-end elsa-justify-center elsa-px-4 elsa-py-6 elsa-pointer-events-none sm:elsa-p-6 sm:elsa-items-start sm:elsa-justify-end">
<div ref={el => this.toast = el}
data-transition-enter="elsa-transform elsa-ease-out elsa-duration-300 elsa-transition"
data-transition-enter-start="elsa-translate-y-2 elsa-opacity-0 sm:elsa-translate-y-0 sm:elsa-translate-x-2"

View file

@ -88,12 +88,16 @@ namespace Elsa.Server.Api.Handlers
var signalRConnectionId = context.WorkflowExecutionContext.WorkflowInstance.GetMetadata("signalRConnectionId")?.ToString();
if (string.IsNullOrWhiteSpace(signalRConnectionId)) return;
var innerMostException = notification.Exception;
while (innerMostException.InnerException != null) innerMostException = innerMostException.InnerException;
var message = new WorkflowTestMessage
{
WorkflowInstanceId = context.WorkflowInstance.Id,
CorrelationId = context.CorrelationId,
ActivityId = context.ActivityId,
Error = notification.Exception.InnerException?.InnerException?.ToString()
Error = innerMostException.ToString()
};
message.WorkflowStatus = message.Status = "Failed";