diff --git a/packages/cli/src/Interfaces.ts b/packages/cli/src/Interfaces.ts index 7e2b25708c..92f6b4153c 100644 --- a/packages/cli/src/Interfaces.ts +++ b/packages/cli/src/Interfaces.ts @@ -153,7 +153,8 @@ export interface IExecutionsStopData { } export interface IExecutionsSummary { - id: string; + id?: string; // executionIdDb + idActive?: string; // executionIdActive mode: WorkflowExecuteMode; finished?: boolean; retryOf?: string; @@ -238,14 +239,23 @@ export interface IPushData { type: IPushDataType; } -export type IPushDataType = 'executionFinished' | 'nodeExecuteAfter' | 'nodeExecuteBefore' | 'testWebhookDeleted' | 'testWebhookReceived'; +export type IPushDataType = 'executionFinished' | 'executionStarted' | 'nodeExecuteAfter' | 'nodeExecuteBefore' | 'testWebhookDeleted' | 'testWebhookReceived'; export interface IPushDataExecutionFinished { data: IRun; - executionId: string; + executionIdActive: string; + executionIdDb?: string; } +export interface IPushDataExecutionStarted { + executionId: string; + mode: WorkflowExecuteMode; + startedAt: Date; + retryOf?: string; + workflowId: string; + workflowName?: string; +} export interface IPushDataNodeExecuteAfter { data: ITaskData; diff --git a/packages/cli/src/Push.ts b/packages/cli/src/Push.ts index 5d76c89294..fb91f92f76 100644 --- a/packages/cli/src/Push.ts +++ b/packages/cli/src/Push.ts @@ -59,8 +59,11 @@ export class Push { * @param {*} data * @memberof Push */ - send(sessionId: string, type: IPushDataType, data: any) { // tslint:disable-line:no-any - if (this.connections[sessionId] === undefined) { + + + + send(type: IPushDataType, data: any, sessionId?: string) { // tslint:disable-line:no-any + if (sessionId !== undefined && this.connections[sessionId] === undefined) { // TODO: Log that properly! console.error(`The session "${sessionId}" is not registred.`); return; @@ -71,7 +74,14 @@ export class Push { data, }; - this.channel.send(JSON.stringify(sendData), [this.connections[sessionId]]); + if (sessionId === undefined) { + // Send to all connected clients + this.channel.send(JSON.stringify(sendData)); + } else { + // Send only to a specific client + this.channel.send(JSON.stringify(sendData), [this.connections[sessionId]]); + } + } } diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 12932dab1d..c9893e6ca8 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -848,7 +848,7 @@ class App { } returnData.push( { - id: data.id.toString(), + idActive: data.id.toString(), workflowId: data.workflowId, mode:data.mode, startedAt: new Date(data.startedAt), diff --git a/packages/cli/src/TestWebhooks.ts b/packages/cli/src/TestWebhooks.ts index 868020d7de..e410754b9d 100644 --- a/packages/cli/src/TestWebhooks.ts +++ b/packages/cli/src/TestWebhooks.ts @@ -91,7 +91,7 @@ export class TestWebhooks { // Inform editor-ui that webhook got received if (this.testWebhookData[webhookKey].sessionId !== undefined) { - pushInstance.send(this.testWebhookData[webhookKey].sessionId!, 'testWebhookReceived', { workflowId: webhookData.workflow.id }); + pushInstance.send('testWebhookReceived', { workflowId: webhookData.workflow.id }, this.testWebhookData[webhookKey].sessionId!); } } catch (error) { @@ -167,7 +167,7 @@ export class TestWebhooks { // Inform editor-ui that webhook got received if (this.testWebhookData[webhookKey].sessionId !== undefined) { try { - pushInstance.send(this.testWebhookData[webhookKey].sessionId!, 'testWebhookDeleted', { workflowId }); + pushInstance.send('testWebhookDeleted', { workflowId }, this.testWebhookData[webhookKey].sessionId!); } catch (error) { // Could not inform editor, probably is not connected anymore. So sipmly go on. } diff --git a/packages/cli/src/WorkflowExecuteAdditionalData.ts b/packages/cli/src/WorkflowExecuteAdditionalData.ts index 78b348a566..4b6793ade8 100644 --- a/packages/cli/src/WorkflowExecuteAdditionalData.ts +++ b/packages/cli/src/WorkflowExecuteAdditionalData.ts @@ -3,6 +3,7 @@ import { IExecutionDb, IExecutionFlattedDb, IPushDataExecutionFinished, + IPushDataExecutionStarted, IPushDataNodeExecuteAfter, IPushDataNodeExecuteBefore, IWorkflowBase, @@ -60,11 +61,45 @@ function executeErrorWorkflow(workflowData: IWorkflowBase, fullRunData: IRun, mo } +/** + * Pushes the execution out to all connected clients + * + * @param {IRun} fullRunData The RunData of the finished execution + * @param {string} executionIdActive The id of the finished execution + * @param {string} [executionIdDb] The database id of finished execution + */ +function pushExecutionFinished(fullRunData: IRun, executionIdActive: string, executionIdDb?: string) { + // Clone the object except the runData. That one is not supposed + // to be send. Because that data got send piece by piece after + // each node which finished executing + const pushRunData = { + ...fullRunData, + data: { + ...fullRunData.data, + resultData: { + ...fullRunData.data.resultData, + runData: {}, + }, + }, + }; + + // Push data to editor-ui once workflow finished + const sendData: IPushDataExecutionFinished = { + executionIdActive, + executionIdDb, + data: pushRunData, + }; + + pushInstance.send('executionFinished', sendData); +} + + const hooks = (mode: WorkflowExecuteMode, workflowData: IWorkflowBase, workflowInstance: Workflow, sessionId?: string, retryOf?: string) => { return { nodeExecuteBefore: [ async (executionId: string, nodeName: string): Promise => { if (sessionId === undefined) { + // Only push data to the session which started it return; } @@ -73,7 +108,7 @@ const hooks = (mode: WorkflowExecuteMode, workflowData: IWorkflowBase, workflowI nodeName, }; - pushInstance.send(sessionId, 'nodeExecuteBefore', sendData); + pushInstance.send('nodeExecuteBefore', sendData, sessionId); }, ], nodeExecuteAfter: [ @@ -88,36 +123,27 @@ const hooks = (mode: WorkflowExecuteMode, workflowData: IWorkflowBase, workflowI data, }; - pushInstance.send(sessionId, 'nodeExecuteAfter', sendData); + pushInstance.send('nodeExecuteAfter', sendData, sessionId); }, ], + workflowExecuteBefore: [ + async (executionId: string): Promise => { + // Push data to editor-ui once workflow finished + const sendData: IPushDataExecutionStarted = { + executionId, + mode, + startedAt: new Date(), + retryOf, + workflowId: workflowData.id as string, + workflowName: workflowData.name, + }; + + pushInstance.send('executionStarted', sendData); + } + ], workflowExecuteAfter: [ async (fullRunData: IRun, executionId: string): Promise => { try { - if (sessionId !== undefined) { - // Clone the object except the runData. That one is not supposed - // to be send. Because that data got send piece by piece after - // each node which finished executing - const pushRunData = { - ...fullRunData, - data: { - ...fullRunData.data, - resultData: { - ...fullRunData.data.resultData, - runData: {}, - }, - }, - }; - - // Push data to editor-ui once workflow finished - const sendData: IPushDataExecutionFinished = { - executionId, - data: pushRunData, - }; - - pushInstance.send(sessionId, 'executionFinished', sendData); - } - const workflowSavePromise = WorkflowHelpers.saveStaticData(workflowInstance); let saveManualExecutions = config.get('executions.saveDataManualExecutions') as boolean; @@ -132,6 +158,7 @@ const hooks = (mode: WorkflowExecuteMode, workflowData: IWorkflowBase, workflowI await workflowSavePromise; } + pushExecutionFinished(fullRunData, executionId); executeErrorWorkflow(workflowData, fullRunData, mode); return; } @@ -148,6 +175,7 @@ const hooks = (mode: WorkflowExecuteMode, workflowData: IWorkflowBase, workflowI if (workflowDidSucceed === true && saveDataSuccessExecution === 'none' || workflowDidSucceed === false && saveDataErrorExecution === 'none' ) { + pushExecutionFinished(fullRunData, executionId); executeErrorWorkflow(workflowData, fullRunData, mode); return; } @@ -185,8 +213,10 @@ const hooks = (mode: WorkflowExecuteMode, workflowData: IWorkflowBase, workflowI await workflowSavePromise; } + pushExecutionFinished(fullRunData, executionId, executionResult.id as string); executeErrorWorkflow(workflowData, fullRunData, mode, executionResult ? executionResult.id as string : undefined); } catch (error) { + pushExecutionFinished(fullRunData, executionId); executeErrorWorkflow(workflowData, fullRunData, mode); } }, diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index 30be24a83e..5beb0055da 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -294,7 +294,8 @@ export interface IExecutionsListResponse { } export interface IExecutionsCurrentSummaryExtended { - id: string; + id?: string; + idActive: string; finished?: boolean; mode: WorkflowExecuteMode; startedAt: Date; @@ -311,7 +312,8 @@ export interface IExecutionsStopData { } export interface IExecutionsSummary { - id: string; + id?: string; // executionIdDb + idActive?: string; // executionIdActive mode: WorkflowExecuteMode; finished?: boolean; retryOf?: string; @@ -333,10 +335,25 @@ export interface IPushData { type: IPushDataType; } -export type IPushDataType = 'executionFinished' | 'nodeExecuteAfter' | 'nodeExecuteBefore' | 'testWebhookDeleted' | 'testWebhookReceived'; +export type IPushDataType = 'executionFinished' | 'executionStarted' | 'nodeExecuteAfter' | 'nodeExecuteBefore' | 'testWebhookDeleted' | 'testWebhookReceived'; + +export interface IPushDataExecutionStarted { + executionId: string; + mode: WorkflowExecuteMode; + startedAt: Date; + retryOf?: string; + workflowId: string; + workflowName?: string; +} + export interface IPushDataExecutionFinished { data: IRun; + executionIdActive: string; + executionIdDb?: string; +} + +export interface IPushDataExecutionStarted { executionId: string; } diff --git a/packages/editor-ui/src/components/ExecutionTime.vue b/packages/editor-ui/src/components/ExecutionTime.vue new file mode 100644 index 0000000000..4cbae59392 --- /dev/null +++ b/packages/editor-ui/src/components/ExecutionTime.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/packages/editor-ui/src/components/ExecutionsList.vue b/packages/editor-ui/src/components/ExecutionsList.vue index 08a10ddcf3..8df770b7f3 100644 --- a/packages/editor-ui/src/components/ExecutionsList.vue +++ b/packages/editor-ui/src/components/ExecutionsList.vue @@ -16,25 +16,7 @@ -   - - - Auto-Refresh: - - - - - - - - - - Manual Refresh - +   @@ -46,26 +28,27 @@ - +