Add more frontend hooks (#1687)

*  add hook for nodecreatelist mount

*  add hook for nodeCreateList selectedTypeChanged

*  add hook for nodeCreateList nodeFilterChanged

*  add hook for nodeCreateList filteredNodeTypesComputed

*  add hook for nodeView.activeNodeChanged

*  add hook for credentialsEdit credentialTypeChanged

*  add hook for onDocumentationUrlClick

*  add hook for executionsList openDialog

*  add hook for execution open

*  add hook for credentialsList dialogVisibleChanged

*  add hook for workflowSettings

*  add hook for showMessage showError

*  add hook for nodeView createNodeActiveChanged

*  add hook for nodeView addNodeButton

*  cleanup

*  add hook for workflowRun runWorkflow

*  add hook for pushConnection executionFinished

*  add hook for runData.displayModeChanged

*  update nodeCreateList.nodeFilterChanged hook

*  update dataDisplay nodeTypeChanged hook

*  update dataDisplay nodeTypeChanged hook

*  update dataDisplay nodeTypeChanged hook

*  update error data in hooks

* update workflowRun runError hook

*  Minor improvements

Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
Ahsan Virani 2021-05-06 02:46:33 +02:00 committed by GitHub
parent f324fe1dff
commit 2052cadce9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 143 additions and 54 deletions

View file

@ -50,6 +50,7 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { externalHooks } from '@/components/mixins/externalHooks';
import { restApi } from '@/components/mixins/restApi'; import { restApi } from '@/components/mixins/restApi';
import { showMessage } from '@/components/mixins/showMessage'; import { showMessage } from '@/components/mixins/showMessage';
import CredentialsInput from '@/components/CredentialsInput.vue'; import CredentialsInput from '@/components/CredentialsInput.vue';
@ -71,6 +72,7 @@ import { INodeUi } from '../Interface';
export default mixins( export default mixins(
restApi, restApi,
showMessage, showMessage,
externalHooks,
).extend({ ).extend({
name: 'CredentialsEdit', name: 'CredentialsEdit',
props: [ props: [
@ -195,7 +197,6 @@ export default mixins(
}); });
return; return;
} }
this.credentialData = currentCredentials; this.credentialData = currentCredentials;
} else { } else {
Vue.nextTick(() => { Vue.nextTick(() => {
@ -227,6 +228,9 @@ export default mixins(
this.credentialType = null; this.credentialType = null;
} }
}, },
async credentialType (newValue, oldValue) {
this.$externalHooks().run('credentialsEdit.credentialTypeChanged', { newValue, oldValue, editCredentials: !!this.editCredentials, credentialType: this.credentialType, setCredentialType: this.setCredentialType });
},
}, },
methods: { methods: {
getCredentialProperties (name: string): INodeProperties[] { getCredentialProperties (name: string): INodeProperties[] {

View file

@ -37,6 +37,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { externalHooks } from '@/components/mixins/externalHooks';
import { restApi } from '@/components/mixins/restApi'; import { restApi } from '@/components/mixins/restApi';
import { ICredentialsResponse } from '@/Interface'; import { ICredentialsResponse } from '@/Interface';
import { nodeHelpers } from '@/components/mixins/nodeHelpers'; import { nodeHelpers } from '@/components/mixins/nodeHelpers';
@ -47,6 +48,7 @@ import { genericHelpers } from '@/components/mixins/genericHelpers';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
export default mixins( export default mixins(
externalHooks,
genericHelpers, genericHelpers,
nodeHelpers, nodeHelpers,
restApi, restApi,
@ -75,6 +77,7 @@ export default mixins(
this.loadCredentials(); this.loadCredentials();
this.loadCredentialTypes(); this.loadCredentialTypes();
} }
this.$externalHooks().run('credentialsList.dialogVisibleChanged', { dialogVisible: newValue });
}, },
}, },
methods: { methods: {

View file

@ -26,7 +26,7 @@
</svg> </svg>
<div v-if="showDocumentHelp && nodeType" class="text"> <div v-if="showDocumentHelp && nodeType" class="text">
Need help? <a id="doc-hyperlink" v-if="showDocumentHelp && nodeType" :href="documentationUrl" target="_blank">Open {{nodeType.displayName}} documentation</a> Need help? <a id="doc-hyperlink" v-if="showDocumentHelp && nodeType" :href="documentationUrl" target="_blank" @click="onDocumentationUrlClick">Open {{nodeType.displayName}} documentation</a>
</div> </div>
</div> </div>
</transition> </transition>
@ -49,10 +49,16 @@ import {
IUpdateInformation, IUpdateInformation,
} from '../Interface'; } from '../Interface';
import { externalHooks } from '@/components/mixins/externalHooks';
import { nodeHelpers } from '@/components/mixins/nodeHelpers';
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
import NodeSettings from '@/components/NodeSettings.vue'; import NodeSettings from '@/components/NodeSettings.vue';
import RunData from '@/components/RunData.vue'; import RunData from '@/components/RunData.vue';
export default Vue.extend({ import mixins from 'vue-typed-mixins';
export default mixins(externalHooks, nodeHelpers, workflowHelpers).extend({
name: 'DataDisplay', name: 'DataDisplay',
components: { components: {
NodeSettings, NodeSettings,
@ -88,6 +94,13 @@ export default Vue.extend({
return null; return null;
}, },
}, },
watch: {
node (node, oldNode) {
if(node && !oldNode) {
this.$externalHooks().run('dataDisplay.nodeTypeChanged', { nodeSubtitle: this.getNodeSubtitle(node, this.nodeType, this.getWorkflow()) });
}
},
},
methods: { methods: {
valueChanged (parameterData: IUpdateInformation) { valueChanged (parameterData: IUpdateInformation) {
this.$emit('valueChanged', parameterData); this.$emit('valueChanged', parameterData);
@ -102,6 +115,9 @@ export default Vue.extend({
this.$store.commit('setActiveNode', null); this.$store.commit('setActiveNode', null);
} }
}, },
onDocumentationUrlClick () {
this.$externalHooks().run('dataDisplay.onDocumentationUrlClick', { nodeType: this.nodeType, documentationUrl: this.documentationUrl });
},
}, },
}); });

View file

@ -158,6 +158,7 @@ import Vue from 'vue';
import ExecutionTime from '@/components/ExecutionTime.vue'; import ExecutionTime from '@/components/ExecutionTime.vue';
import WorkflowActivator from '@/components/WorkflowActivator.vue'; import WorkflowActivator from '@/components/WorkflowActivator.vue';
import { externalHooks } from '@/components/mixins/externalHooks';
import { restApi } from '@/components/mixins/restApi'; import { restApi } from '@/components/mixins/restApi';
import { genericHelpers } from '@/components/mixins/genericHelpers'; import { genericHelpers } from '@/components/mixins/genericHelpers';
import { showMessage } from '@/components/mixins/showMessage'; import { showMessage } from '@/components/mixins/showMessage';
@ -182,6 +183,7 @@ import {
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
export default mixins( export default mixins(
externalHooks,
genericHelpers, genericHelpers,
restApi, restApi,
showMessage, showMessage,
@ -558,6 +560,8 @@ export default mixins(
await this.loadWorkflows(); await this.loadWorkflows();
await this.refreshData(); await this.refreshData();
this.handleAutoRefreshToggle(); this.handleAutoRefreshToggle();
this.$externalHooks().run('executionsList.openDialog');
}, },
async retryExecution (execution: IExecutionShortResponse, loadWorkflow?: boolean) { async retryExecution (execution: IExecutionShortResponse, loadWorkflow?: boolean) {
this.isDataLoading = true; this.isDataLoading = true;

View file

@ -47,14 +47,11 @@
import Vue from 'vue'; import Vue from 'vue';
import { nodeBase } from '@/components/mixins/nodeBase'; import { nodeBase } from '@/components/mixins/nodeBase';
import { nodeHelpers } from '@/components/mixins/nodeHelpers';
import { workflowHelpers } from '@/components/mixins/workflowHelpers'; import { workflowHelpers } from '@/components/mixins/workflowHelpers';
import { import {
INode,
INodeIssueObjectProperty,
INodePropertyOptions,
INodeTypeDescription, INodeTypeDescription,
ITaskData,
NodeHelpers, NodeHelpers,
} from 'n8n-workflow'; } from 'n8n-workflow';
@ -62,7 +59,7 @@ import NodeIcon from '@/components/NodeIcon.vue';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
export default mixins(nodeBase, workflowHelpers).extend({ export default mixins(nodeBase, nodeHelpers, workflowHelpers).extend({
name: 'Node', name: 'Node',
components: { components: {
NodeIcon, NodeIcon,
@ -133,41 +130,7 @@ export default mixins(nodeBase, workflowHelpers).extend({
} }
}, },
nodeSubtitle (): string | undefined { nodeSubtitle (): string | undefined {
if (this.data.notesInFlow) { return this.getNodeSubtitle(this.data, this.nodeType, this.workflow);
return this.data.notes;
}
if (this.nodeType !== null && this.nodeType.subtitle !== undefined) {
return this.workflow.expression.getSimpleParameterValue(this.data as INode, this.nodeType.subtitle, 'internal') as string | undefined;
}
if (this.data.parameters.operation !== undefined) {
const operation = this.data.parameters.operation as string;
if (this.nodeType === null) {
return operation;
}
const operationData = this.nodeType.properties.find((property) => {
return property.name === 'operation';
});
if (operationData === undefined) {
return operation;
}
if (operationData.options === undefined) {
return operation;
}
const optionData = operationData.options.find((option) => {
return (option as INodePropertyOptions).value === this.data.parameters.operation;
});
if (optionData === undefined) {
return operation;
}
return optionData.name;
}
return undefined;
}, },
workflowRunning (): boolean { workflowRunning (): boolean {
return this.$store.getters.isActionActive('workflowRunning'); return this.$store.getters.isActionActive('workflowRunning');
@ -186,7 +149,7 @@ export default mixins(nodeBase, workflowHelpers).extend({
this.disableNodes([this.data]); this.disableNodes([this.data]);
}, },
executeNode () { executeNode () {
this.$emit('runWorkflow', this.data.name); this.$emit('runWorkflow', this.data.name, 'Node.executeNode');
}, },
deleteNode () { deleteNode () {
Vue.nextTick(() => { Vue.nextTick(() => {

View file

@ -24,10 +24,13 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { externalHooks } from "@/components/mixins/externalHooks";
import { INodeTypeDescription } from 'n8n-workflow'; import { INodeTypeDescription } from 'n8n-workflow';
import NodeCreateItem from '@/components/NodeCreateItem.vue'; import NodeCreateItem from '@/components/NodeCreateItem.vue';
export default Vue.extend({ import mixins from "vue-typed-mixins";
export default mixins(externalHooks).extend({
name: 'NodeCreateList', name: 'NodeCreateList',
components: { components: {
NodeCreateItem, NodeCreateItem,
@ -70,13 +73,18 @@ export default Vue.extend({
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0; return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
}); });
this.$externalHooks().run('nodeCreateList.filteredNodeTypesComputed', { nodeFilter: this.nodeFilter, result: returnData, selectedType: this.selectedType });
return returnData; return returnData;
}, },
}, },
watch: { watch: {
nodeFilter (newVal, oldVal) { nodeFilter (newValue, oldValue) {
// Reset the index whenver the filter-value changes // Reset the index whenver the filter-value changes
this.activeNodeTypeIndex = 0; this.activeNodeTypeIndex = 0;
this.$externalHooks().run('nodeCreateList.nodeFilterChanged', { oldValue, newValue, selectedType: this.selectedType, filteredNodes: this.filteredNodeTypes });
},
selectedType (newValue, oldValue) {
this.$externalHooks().run('nodeCreateList.selectedTypeChanged', { oldValue, newValue });
}, },
}, },
methods: { methods: {
@ -105,6 +113,12 @@ export default Vue.extend({
this.$emit('nodeTypeSelected', nodeTypeName); this.$emit('nodeTypeSelected', nodeTypeName);
}, },
}, },
async mounted() {
this.$externalHooks().run('nodeCreateList.mounted');
},
async destroyed() {
this.$externalHooks().run('nodeCreateList.destroyed');
},
}); });
</script> </script>

View file

@ -5,7 +5,7 @@
<el-button <el-button
v-if="node && !isReadOnly" v-if="node && !isReadOnly"
:disabled="workflowRunning" :disabled="workflowRunning"
@click.stop="runWorkflow(node.name)" @click.stop="runWorkflow(node.name, 'RunData.ExecuteNodeButton')"
class="execute-node-button" class="execute-node-button"
:title="`Executes this ${node.name} node after executing any previous nodes that have not yet returned data`" :title="`Executes this ${node.name} node after executing any previous nodes that have not yet returned data`"
> >
@ -228,6 +228,7 @@ import BinaryDataDisplay from '@/components/BinaryDataDisplay.vue';
import NodeErrorView from '@/components/Error/NodeViewError.vue'; import NodeErrorView from '@/components/Error/NodeViewError.vue';
import { copyPaste } from '@/components/mixins/copyPaste'; import { copyPaste } from '@/components/mixins/copyPaste';
import { externalHooks } from "@/components/mixins/externalHooks";
import { genericHelpers } from '@/components/mixins/genericHelpers'; import { genericHelpers } from '@/components/mixins/genericHelpers';
import { nodeHelpers } from '@/components/mixins/nodeHelpers'; import { nodeHelpers } from '@/components/mixins/nodeHelpers';
import { workflowRun } from '@/components/mixins/workflowRun'; import { workflowRun } from '@/components/mixins/workflowRun';
@ -239,6 +240,7 @@ const deselectedPlaceholder = '_!^&*';
export default mixins( export default mixins(
copyPaste, copyPaste,
externalHooks,
genericHelpers, genericHelpers,
nodeHelpers, nodeHelpers,
workflowRun, workflowRun,
@ -617,8 +619,9 @@ export default mixins(
jsonData () { jsonData () {
this.refreshDataSize(); this.refreshDataSize();
}, },
displayMode () { displayMode (newValue, oldValue) {
this.closeBinaryDataDisplay(); this.closeBinaryDataDisplay();
this.$externalHooks().run('runData.displayModeChanged', { newValue, oldValue });
}, },
maxRunIndex () { maxRunIndex () {
this.runIndex = Math.min(this.runIndex, this.maxRunIndex); this.runIndex = Math.min(this.runIndex, this.maxRunIndex);

View file

@ -167,6 +167,7 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { externalHooks } from '@/components/mixins/externalHooks';
import { restApi } from '@/components/mixins/restApi'; import { restApi } from '@/components/mixins/restApi';
import { genericHelpers } from '@/components/mixins/genericHelpers'; import { genericHelpers } from '@/components/mixins/genericHelpers';
import { showMessage } from '@/components/mixins/showMessage'; import { showMessage } from '@/components/mixins/showMessage';
@ -180,6 +181,7 @@ import {
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
export default mixins( export default mixins(
externalHooks,
genericHelpers, genericHelpers,
restApi, restApi,
showMessage, showMessage,
@ -225,6 +227,7 @@ export default mixins(
if (newValue) { if (newValue) {
this.openDialog(); this.openDialog();
} }
this.$externalHooks().run('workflowSettings.dialogVisibleChanged', { dialogVisible: newValue });
}, },
}, },
methods: { methods: {
@ -456,6 +459,8 @@ export default mixins(
} }
} }
const oldSettings = JSON.parse(JSON.stringify(this.$store.getters.workflowSettings));
this.$store.commit('setWorkflowSettings', localWorkflowSettings); this.$store.commit('setWorkflowSettings', localWorkflowSettings);
this.isLoading = false; this.isLoading = false;
@ -467,6 +472,8 @@ export default mixins(
}); });
this.closeDialog(); this.closeDialog();
this.$externalHooks().run('workflowSettings.saveSettings', { oldSettings });
}, },
toggleTimeout() { toggleTimeout() {
this.workflowSettings.executionTimeout = this.workflowSettings.executionTimeout === -1 ? 0 : -1; this.workflowSettings.executionTimeout = this.workflowSettings.executionTimeout === -1 ? 0 : -1;

View file

@ -13,6 +13,8 @@ import {
IRunData, IRunData,
IRunExecutionData, IRunExecutionData,
ITaskDataConnections, ITaskDataConnections,
INode,
INodePropertyOptions,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { import {
@ -321,5 +323,43 @@ export const nodeHelpers = mixins(
this.updateNodeCredentialIssues(node); this.updateNodeCredentialIssues(node);
} }
}, },
// @ts-ignore
getNodeSubtitle (data, nodeType, workflow): string | undefined {
if (data.notesInFlow) {
return data.notes;
}
if (nodeType !== null && nodeType.subtitle !== undefined) {
return workflow.expression.getSimpleParameterValue(data as INode, nodeType.subtitle, 'internal') as string | undefined;
}
if (data.parameters.operation !== undefined) {
const operation = data.parameters.operation as string;
if (nodeType === null) {
return operation;
}
const operationData:INodeProperties = nodeType.properties.find((property: INodeProperties) => {
return property.name === 'operation';
});
if (operationData === undefined) {
return operation;
}
if (operationData.options === undefined) {
return operation;
}
const optionData = operationData.options.find((option) => {
return (option as INodePropertyOptions).value === data.parameters.operation;
});
if (optionData === undefined) {
return operation;
}
return optionData.name;
}
return undefined;
},
}, },
}); });

View file

@ -8,6 +8,7 @@ import {
IPushDataTestWebhook, IPushDataTestWebhook,
} from '../../Interface'; } from '../../Interface';
import { externalHooks } from '@/components/mixins/externalHooks';
import { nodeHelpers } from '@/components/mixins/nodeHelpers'; import { nodeHelpers } from '@/components/mixins/nodeHelpers';
import { showMessage } from '@/components/mixins/showMessage'; import { showMessage } from '@/components/mixins/showMessage';
import { titleChange } from '@/components/mixins/titleChange'; import { titleChange } from '@/components/mixins/titleChange';
@ -15,6 +16,7 @@ import { titleChange } from '@/components/mixins/titleChange';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
export const pushConnection = mixins( export const pushConnection = mixins(
externalHooks,
nodeHelpers, nodeHelpers,
showMessage, showMessage,
titleChange, titleChange,
@ -202,6 +204,7 @@ export const pushConnection = mixins(
const runDataExecuted = pushData.data; const runDataExecuted = pushData.data;
let runDataExecutedErrorMessage;
// @ts-ignore // @ts-ignore
const workflow = this.getWorkflow(); const workflow = this.getWorkflow();
if (runDataExecuted.finished !== true) { if (runDataExecuted.finished !== true) {
@ -221,6 +224,9 @@ export const pushConnection = mixins(
: runDataExecuted.data.resultData.error.message; : runDataExecuted.data.resultData.error.message;
errorMessage = `There was a problem executing the workflow:<br /><strong>"${receivedError}"</strong>`; errorMessage = `There was a problem executing the workflow:<br /><strong>"${receivedError}"</strong>`;
} }
runDataExecutedErrorMessage = errorMessage;
this.$titleSet(workflow.name, 'ERROR'); this.$titleSet(workflow.name, 'ERROR');
this.$showMessage({ this.$showMessage({
title: 'Problem executing workflow', title: 'Problem executing workflow',
@ -249,6 +255,20 @@ export const pushConnection = mixins(
// Set the node execution issues on all the nodes which produced an error so that // Set the node execution issues on all the nodes which produced an error so that
// it can be displayed in the node-view // it can be displayed in the node-view
this.updateNodesExecutionIssues(); this.updateNodesExecutionIssues();
let itemsCount = 0;
if(runDataExecuted.data.resultData.lastNodeExecuted && !runDataExecutedErrorMessage) {
itemsCount = runDataExecuted.data.resultData.runData[runDataExecuted.data.resultData.lastNodeExecuted][0].data!.main[0]!.length;
}
this.$externalHooks().run('pushConnection.executionFinished', {
itemsCount,
nodeName: runDataExecuted.data.resultData.lastNodeExecuted,
errorMessage: runDataExecutedErrorMessage,
runDataExecutedStartData: runDataExecuted.data.startData,
resultDataError: runDataExecuted.data.resultData.error,
});
} else if (receivedData.type === 'executionStarted') { } else if (receivedData.type === 'executionStarted') {
const pushData = receivedData.data as IPushDataExecutionStarted; const pushData = receivedData.data as IPushDataExecutionStarted;

View file

@ -2,9 +2,13 @@ import Vue from 'vue';
import { Notification } from 'element-ui'; import { Notification } from 'element-ui';
import { ElNotificationOptions } from 'element-ui/types/notification'; import { ElNotificationOptions } from 'element-ui/types/notification';
import mixins from 'vue-typed-mixins';
import { externalHooks } from '@/components/mixins/externalHooks';
// export const showMessage = { // export const showMessage = {
export const showMessage = Vue.extend({ export const showMessage = mixins(externalHooks).extend({
methods: { methods: {
$showMessage (messageData: ElNotificationOptions) { $showMessage (messageData: ElNotificationOptions) {
messageData.dangerouslyUseHTMLString = true; messageData.dangerouslyUseHTMLString = true;
@ -21,6 +25,7 @@ export const showMessage = Vue.extend({
type: 'error', type: 'error',
duration: 0, duration: 0,
}); });
this.$externalHooks().run('showMessage.showError', { title, message, errorMessage: error.message });
}, },
}, },
}); });

View file

@ -53,7 +53,7 @@ export const workflowRun = mixins(
return response; return response;
}, },
async runWorkflow (nodeName: string): Promise<IExecutionPushResponse | undefined> { async runWorkflow (nodeName: string, source?: string): Promise<IExecutionPushResponse | undefined> {
if (this.$store.getters.isActionActive('workflowRunning') === true) { if (this.$store.getters.isActionActive('workflowRunning') === true) {
return; return;
} }
@ -84,7 +84,7 @@ export const workflowRun = mixins(
duration: 0, duration: 0,
}); });
this.$titleSet(workflow.name as string, 'ERROR'); this.$titleSet(workflow.name as string, 'ERROR');
this.$externalHooks().run('workflow.runError', { errorMessages }); this.$externalHooks().run('workflowRun.runError', { errorMessages, nodeName });
return; return;
} }
} }
@ -172,7 +172,11 @@ export const workflowRun = mixins(
}; };
this.$store.commit('setWorkflowExecutionData', executionData); this.$store.commit('setWorkflowExecutionData', executionData);
return await this.runWorkflowApi(startRunData); const runWorkflowApiResponse = await this.runWorkflowApi(startRunData);
this.$externalHooks().run('workflowRun.runWorkflow', { nodeName, source });
return runWorkflowApiResponse;
} catch (error) { } catch (error) {
this.$titleSet(workflow.name as string, 'ERROR'); this.$titleSet(workflow.name as string, 'ERROR');
this.$showError(error, 'Problem running workflow', 'There was a problem running the workflow:'); this.$showError(error, 'Problem running workflow', 'There was a problem running the workflow:');

View file

@ -198,7 +198,7 @@ export default mixins(
this.createNodeActive = false; this.createNodeActive = false;
}, },
nodes: { nodes: {
async handler (val, oldVal) { async handler (value, oldValue) {
// Load a workflow // Load a workflow
let workflowId = null as string | null; let workflowId = null as string | null;
if (this.$route && this.$route.params.name) { if (this.$route && this.$route.params.name) {
@ -208,7 +208,7 @@ export default mixins(
deep: true, deep: true,
}, },
connections: { connections: {
async handler (val, oldVal) { async handler (value, oldValue) {
// Load a workflow // Load a workflow
let workflowId = null as string | null; let workflowId = null as string | null;
if (this.$route && this.$route.params.name) { if (this.$route && this.$route.params.name) {
@ -332,6 +332,7 @@ export default mixins(
}, },
openNodeCreator () { openNodeCreator () {
this.createNodeActive = true; this.createNodeActive = true;
this.$externalHooks().run('nodeView.createNodeActiveChanged', { source: 'add_node_button' });
}, },
async openExecution (executionId: string) { async openExecution (executionId: string) {
this.resetWorkspace(); this.resetWorkspace();
@ -354,6 +355,8 @@ export default mixins(
this.$store.commit('setWorkflowExecutionData', data); this.$store.commit('setWorkflowExecutionData', data);
await this.addNodes(JSON.parse(JSON.stringify(data.workflowData.nodes)), JSON.parse(JSON.stringify(data.workflowData.connections))); await this.addNodes(JSON.parse(JSON.stringify(data.workflowData.nodes)), JSON.parse(JSON.stringify(data.workflowData.connections)));
this.$externalHooks().run('execution.open', { workflowId: data.workflowData.id, workflowName: data.workflowData.name, executionId });
}, },
async openWorkflow (workflowId: string) { async openWorkflow (workflowId: string) {
this.resetWorkspace(); this.resetWorkspace();
@ -1052,6 +1055,8 @@ export default mixins(
this.$store.commit('setStateDirty', true); this.$store.commit('setStateDirty', true);
this.$externalHooks().run('nodeView.addNodeButton', { nodeTypeName });
// Automatically deselect all nodes and select the current one and also active // Automatically deselect all nodes and select the current one and also active
// current node // current node
this.deselectAllNodes(); this.deselectAllNodes();
@ -1174,6 +1179,7 @@ export default mixins(
// Display the node-creator // Display the node-creator
this.createNodeActive = true; this.createNodeActive = true;
this.$externalHooks().run('nodeView.createNodeActiveChanged', { source: 'node_connection_drop' });
}); });
this.instance.bind('connection', (info: OnConnectionBindInfo) => { this.instance.bind('connection', (info: OnConnectionBindInfo) => {