From 885dba6f1210f7f7a49ea11b215bb0ec49711907 Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Wed, 6 Dec 2023 17:28:09 +0200 Subject: [PATCH] refactor: Migrate externalHooks mixin to composables (no-changelog) (#7930) ## Summary Provide details about your pull request and what it adds, fixes, or changes. Photos and videos are recommended. As part of NodeView refactor, this PR migrates all externalHooks calls to `useExternalHooks` composable. #### How to test the change: 1. Run using env `export N8N_DEPLOYMENT_TYPE=cloud` 2. Hooks should still run as expected ## Issues fixed Include links to Github issue or Community forum post or **Linear ticket**: > Important in order to close automatically and provide context to reviewers https://linear.app/n8n/issue/N8N-6349/externalhooks ## Review / Merge checklist - [x] PR title and summary are descriptive. **Remember, the title automatically goes into the changelog. Use `(no-changelog)` otherwise.** ([conventions](https://github.com/n8n-io/n8n/blob/master/.github/pull_request_title_conventions.md)) - [x] [Docs updated](https://github.com/n8n-io/n8n-docs) or follow-up ticket created. - [x] Tests included. > A bug is not considered fixed, unless a test is added to prevent it from happening again. A feature is not complete without tests. > > *(internal)* You can use Slack commands to trigger [e2e tests](https://www.notion.so/n8n/How-to-use-Test-Instances-d65f49dfc51f441ea44367fb6f67eb0a?pvs=4#a39f9e5ba64a48b58a71d81c837e8227) or [deploy test instance](https://www.notion.so/n8n/How-to-use-Test-Instances-d65f49dfc51f441ea44367fb6f67eb0a?pvs=4#f6a177d32bde4b57ae2da0b8e454bfce) or [deploy early access version on Cloud](https://www.notion.so/n8n/Cloudbot-3dbe779836004972b7057bc989526998?pvs=4#fef2d36ab02247e1a0f65a74f6fb534e). --- packages/editor-ui/src/App.vue | 3 +- packages/editor-ui/src/Interface.ts | 5 --- .../CredentialEdit/CredentialEdit.vue | 13 ++++--- .../src/components/CredentialsSelectModal.vue | 11 ++++-- .../src/components/ExecutionsList.vue | 8 ++-- .../ExecutionsView/ExecutionsList.vue | 6 ++- .../src/components/ExpressionEdit.vue | 16 +++++--- .../src/components/MainHeader/MainHeader.vue | 6 +-- .../editor-ui/src/components/MainSidebar.vue | 10 +++-- packages/editor-ui/src/components/Node.vue | 8 ++-- .../Node/NodeCreator/Modes/ActionsMode.vue | 6 +-- .../NodeCreator/composables/useActions.ts | 4 +- .../src/components/NodeDetailsView.vue | 15 +++++--- .../src/components/NodeExecuteButton.vue | 10 +++-- .../editor-ui/src/components/NodeSettings.vue | 16 +++++--- .../src/components/NodeSettingsTabs.vue | 11 ++++-- .../src/components/ParameterInput.vue | 14 ++++--- .../src/components/ParameterInputFull.vue | 2 - .../src/components/PersonalizationModal.vue | 6 ++- packages/editor-ui/src/components/RunData.vue | 11 ++++-- .../editor-ui/src/components/RunDataJson.vue | 8 ++-- .../src/components/RunDataSchema.vue | 5 ++- .../editor-ui/src/components/RunDataTable.vue | 11 ++++-- packages/editor-ui/src/components/Sticky.vue | 4 +- .../editor-ui/src/components/Telemetry.vue | 2 - .../src/components/VariableSelectorItem.vue | 2 - .../src/components/WorkerList.ee.vue | 7 ++-- .../src/components/WorkflowActivator.vue | 4 +- .../src/components/WorkflowLMChat.vue | 10 +++-- .../src/components/WorkflowSettings.vue | 13 ++++--- .../src/composables/useExternalHooks.ts | 37 +++++++++++++++++-- packages/editor-ui/src/hooks/register.ts | 25 ++++++++++++- .../editor-ui/src/mixins/externalHooks.ts | 37 ------------------- packages/editor-ui/src/mixins/pinData.ts | 3 +- .../editor-ui/src/mixins/pushConnection.ts | 6 +-- .../editor-ui/src/mixins/workflowActivate.ts | 8 ++-- .../editor-ui/src/mixins/workflowHelpers.ts | 8 ++-- packages/editor-ui/src/mixins/workflowRun.ts | 8 ++-- packages/editor-ui/src/router.ts | 4 +- packages/editor-ui/src/utils/externalHooks.ts | 33 ----------------- packages/editor-ui/src/views/NodeView.vue | 35 +++++++++--------- .../src/views/SettingsCommunityNodesView.vue | 13 ++++--- .../SetupWorkflowFromTemplateView.vue | 24 ++++-------- .../setupTemplate.store.ts | 20 +++++----- .../src/views/TemplatesCollectionView.vue | 10 ++++- .../src/views/TemplatesWorkflowView.vue | 10 ++++- 46 files changed, 287 insertions(+), 241 deletions(-) delete mode 100644 packages/editor-ui/src/mixins/externalHooks.ts delete mode 100644 packages/editor-ui/src/utils/externalHooks.ts diff --git a/packages/editor-ui/src/App.vue b/packages/editor-ui/src/App.vue index 3eb8160675..e8978ae785 100644 --- a/packages/editor-ui/src/App.vue +++ b/packages/editor-ui/src/App.vue @@ -59,7 +59,6 @@ import { useUsageStore } from '@/stores/usage.store'; import { useUsersStore } from '@/stores/users.store'; import { useHistoryHelper } from '@/composables/useHistoryHelper'; import { useRoute } from 'vue-router'; -import { runExternalHook } from '@/utils/externalHooks'; import { initializeAuthenticatedFeatures } from '@/init'; export default defineComponent({ @@ -119,7 +118,7 @@ export default defineComponent({ void this.checkForNewVersions(); void initializeAuthenticatedFeatures(); - void runExternalHook('app.mount'); + void useExternalHooks().run('app.mount'); this.loading = false; }, watch: { diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index f525d5bf13..7e8b6cb587 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -51,7 +51,6 @@ import type { BulkCommand, Undoable } from '@/models/history'; import type { PartialBy, TupleToUnion } from '@/utils/typeHelpers'; import type { Component } from 'vue'; import type { Scope } from '@n8n/permissions'; -import type { runExternalHook } from '@/utils/externalHooks'; export * from 'n8n-design-system/types'; @@ -161,10 +160,6 @@ export interface INodeTypesMaxCount { }; } -export interface IExternalHooks { - run: typeof runExternalHook; -} - export interface INodeTranslationHeaders { data: { [key: string]: { diff --git a/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue b/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue index 36d2cd0959..02a41a58ef 100644 --- a/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue +++ b/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue @@ -164,7 +164,7 @@ import { } from '@/utils/nodeTypesUtils'; import { isValidCredentialResponse, isCredentialModalState } from '@/utils/typeGuards'; import { isExpression, isTestableExpression } from '@/utils/expressions'; -import { externalHooks } from '@/mixins/externalHooks'; +import { useExternalHooks } from '@/composables/useExternalHooks'; interface NodeAccessMap { [nodeType: string]: ICredentialNodeAccess | null; @@ -172,7 +172,7 @@ interface NodeAccessMap { export default defineComponent({ name: 'CredentialEdit', - mixins: [nodeHelpers, externalHooks], + mixins: [nodeHelpers], components: { CredentialSharing, CredentialConfig, @@ -198,6 +198,7 @@ export default defineComponent({ }, setup() { return { + externalHooks: useExternalHooks(), ...useToast(), ...useMessage(), }; @@ -266,7 +267,7 @@ export default defineComponent({ } } - await this.$externalHooks().run('credentialsEdit.credentialModalOpened', { + await this.externalHooks.run('credentialsEdit.credentialModalOpened', { credentialType: this.credentialTypeName, isEditingCredential: this.mode === 'edit', activeNode: this.ndvStore.activeNode, @@ -876,7 +877,7 @@ export default defineComponent({ } this.$telemetry.track('User saved credentials', trackProperties); - await this.$externalHooks().run('credentialEdit.saveCredential', trackProperties); + await this.externalHooks.run('credentialEdit.saveCredential', trackProperties); } return credential; @@ -899,7 +900,7 @@ export default defineComponent({ return null; } - await this.$externalHooks().run('credential.saved', { + await this.externalHooks.run('credential.saved', { credential_type: credentialDetails.type, credential_id: credential.id, is_new: true, @@ -933,7 +934,7 @@ export default defineComponent({ return null; } - await this.$externalHooks().run('credential.saved', { + await this.externalHooks.run('credential.saved', { credential_type: credentialDetails.type, credential_id: credential.id, is_new: false, diff --git a/packages/editor-ui/src/components/CredentialsSelectModal.vue b/packages/editor-ui/src/components/CredentialsSelectModal.vue index 4716125c11..4a64cca222 100644 --- a/packages/editor-ui/src/components/CredentialsSelectModal.vue +++ b/packages/editor-ui/src/components/CredentialsSelectModal.vue @@ -61,19 +61,24 @@ import { defineComponent } from 'vue'; import Modal from './Modal.vue'; import { CREDENTIAL_SELECT_MODAL_KEY } from '../constants'; -import { externalHooks } from '@/mixins/externalHooks'; import { mapStores } from 'pinia'; import { useUIStore } from '@/stores/ui.store'; import { useWorkflowsStore } from '@/stores/workflows.store'; import { useCredentialsStore } from '@/stores/credentials.store'; import { createEventBus } from 'n8n-design-system/utils'; +import { useExternalHooks } from '@/composables/useExternalHooks'; export default defineComponent({ name: 'CredentialsSelectModal', - mixins: [externalHooks], components: { Modal, }, + setup() { + const externalHooks = useExternalHooks(); + return { + externalHooks, + }; + }, async mounted() { try { await this.credentialsStore.fetchCredentialTypes(false); @@ -114,7 +119,7 @@ export default defineComponent({ }; this.$telemetry.track('User opened Credential modal', telemetryPayload); - void this.$externalHooks().run('credentialsSelectModal.openCredentialType', telemetryPayload); + void this.externalHooks.run('credentialsSelectModal.openCredentialType', telemetryPayload); }, }, }); diff --git a/packages/editor-ui/src/components/ExecutionsList.vue b/packages/editor-ui/src/components/ExecutionsList.vue index d694a5908a..efe0852110 100644 --- a/packages/editor-ui/src/components/ExecutionsList.vue +++ b/packages/editor-ui/src/components/ExecutionsList.vue @@ -287,7 +287,6 @@ import { defineComponent } from 'vue'; import { mapStores } from 'pinia'; import ExecutionTime from '@/components/ExecutionTime.vue'; import ExecutionFilter from '@/components/ExecutionFilter.vue'; -import { externalHooks } from '@/mixins/externalHooks'; import { MODAL_CONFIRM, VIEWS, WAIT_TIME_UNLIMITED } from '@/constants'; import { genericHelpers } from '@/mixins/genericHelpers'; import { executionHelpers } from '@/mixins/executionsHelpers'; @@ -310,10 +309,11 @@ import { useWorkflowsStore } from '@/stores/workflows.store'; import { isEmpty } from '@/utils/typesUtils'; import { setPageTitle } from '@/utils/htmlUtils'; import { executionFilterToQueryFilter } from '@/utils/executionUtils'; +import { useExternalHooks } from '@/composables/useExternalHooks'; export default defineComponent({ name: 'ExecutionsList', - mixins: [externalHooks, genericHelpers, executionHelpers], + mixins: [genericHelpers, executionHelpers], components: { ExecutionTime, ExecutionFilter, @@ -327,10 +327,12 @@ export default defineComponent({ setup() { const i18n = useI18n(); const telemetry = useTelemetry(); + const externalHooks = useExternalHooks(); return { i18n, telemetry, + externalHooks, ...useToast(), ...useMessage(), }; @@ -368,7 +370,7 @@ export default defineComponent({ async created() { await this.loadWorkflows(); - void this.$externalHooks().run('executionsList.openDialog'); + void this.externalHooks.run('executionsList.openDialog'); this.telemetry.track('User opened Executions log', { workflow_id: this.workflowsStore.workflowId, }); diff --git a/packages/editor-ui/src/components/ExecutionsView/ExecutionsList.vue b/packages/editor-ui/src/components/ExecutionsView/ExecutionsList.vue index 3b6a08b1d7..2b732b11c2 100644 --- a/packages/editor-ui/src/components/ExecutionsView/ExecutionsList.vue +++ b/packages/editor-ui/src/components/ExecutionsView/ExecutionsList.vue @@ -68,6 +68,7 @@ import { useSettingsStore } from '@/stores/settings.store'; import { useNodeTypesStore } from '@/stores/nodeTypes.store'; import { useTagsStore } from '@/stores/tags.store'; import { executionFilterToQueryFilter } from '@/utils/executionUtils'; +import { useExternalHooks } from '@/composables/useExternalHooks'; // Number of execution pages that are fetched before temporary execution card is shown const MAX_LOADING_ATTEMPTS = 5; @@ -91,7 +92,10 @@ export default defineComponent({ }; }, setup() { + const externalHooks = useExternalHooks(); + return { + externalHooks, ...useToast(), ...useMessage(), }; @@ -586,7 +590,7 @@ export default defineComponent({ this.tagsStore.upsertTags(tags); - void this.$externalHooks().run('workflow.open', { workflowId, workflowName: data.name }); + void this.externalHooks.run('workflow.open', { workflowId, workflowName: data.name }); this.uiStore.stateIsDirty = false; }, async addNodes(nodes: INodeUi[], connections?: IConnections) { diff --git a/packages/editor-ui/src/components/ExpressionEdit.vue b/packages/editor-ui/src/components/ExpressionEdit.vue index 1c42692a49..a904380cc0 100644 --- a/packages/editor-ui/src/components/ExpressionEdit.vue +++ b/packages/editor-ui/src/components/ExpressionEdit.vue @@ -87,7 +87,6 @@ import VariableSelector from '@/components/VariableSelector.vue'; import type { IVariableItemSelected } from '@/Interface'; -import { externalHooks } from '@/mixins/externalHooks'; import { genericHelpers } from '@/mixins/genericHelpers'; import { EXPRESSIONS_DOCS_URL } from '@/constants'; @@ -95,14 +94,21 @@ import { EXPRESSIONS_DOCS_URL } from '@/constants'; import { debounceHelper } from '@/mixins/debounce'; import { useWorkflowsStore } from '@/stores/workflows.store'; import { useNDVStore } from '@/stores/ndv.store'; +import { useExternalHooks } from '@/composables/useExternalHooks'; import { createExpressionTelemetryPayload } from '@/utils/telemetryUtils'; import type { Segment } from '@/types/expressions'; export default defineComponent({ name: 'ExpressionEdit', - mixins: [externalHooks, genericHelpers, debounceHelper], + mixins: [genericHelpers, debounceHelper], props: ['dialogVisible', 'parameter', 'path', 'modelValue', 'eventSource', 'redactValues'], + setup() { + const externalHooks = useExternalHooks(); + return { + externalHooks, + }; + }, components: { ExpressionEditorModalInput, ExpressionEditorModalOutput, @@ -152,7 +158,7 @@ export default defineComponent({ itemSelected: (variable: IVariableItemSelected) => void; } ).itemSelected(eventData); - void this.$externalHooks().run('expressionEdit.itemSelected', { + void this.externalHooks.run('expressionEdit.itemSelected', { parameter: this.parameter, value: this.modelValue, selectedItem: eventData, @@ -233,7 +239,7 @@ export default defineComponent({ getValue: () => string; } )?.getValue() || ''; - void this.$externalHooks().run('expressionEdit.dialogVisibleChanged', { + void this.externalHooks.run('expressionEdit.dialogVisibleChanged', { dialogVisible: newValue, parameter: this.parameter, value: this.modelValue, @@ -250,7 +256,7 @@ export default defineComponent({ ); this.$telemetry.track('User closed Expression Editor', telemetryPayload); - void this.$externalHooks().run('expressionEdit.closeDialog', telemetryPayload); + void this.externalHooks.run('expressionEdit.closeDialog', telemetryPayload); } }, }, diff --git a/packages/editor-ui/src/components/MainHeader/MainHeader.vue b/packages/editor-ui/src/components/MainHeader/MainHeader.vue index fb3d053044..85ed4344fe 100644 --- a/packages/editor-ui/src/components/MainHeader/MainHeader.vue +++ b/packages/editor-ui/src/components/MainHeader/MainHeader.vue @@ -41,12 +41,12 @@ export default defineComponent({ TabBar, }, mixins: [pushConnection, workflowHelpers], - setup(props) { + setup(props, ctx) { return { // eslint-disable-next-line @typescript-eslint/no-misused-promises - ...pushConnection.setup?.(props), + ...pushConnection.setup?.(props, ctx), // eslint-disable-next-line @typescript-eslint/no-misused-promises - ...workflowHelpers.setup?.(props), + ...workflowHelpers.setup?.(props, ctx), }; }, data() { diff --git a/packages/editor-ui/src/components/MainSidebar.vue b/packages/editor-ui/src/components/MainSidebar.vue index 384452311f..b60d85eee0 100644 --- a/packages/editor-ui/src/components/MainSidebar.vue +++ b/packages/editor-ui/src/components/MainSidebar.vue @@ -121,6 +121,7 @@ import { isNavigationFailure } from 'vue-router'; import ExecutionsUsage from '@/components/ExecutionsUsage.vue'; import MainSidebarSourceControl from '@/components/MainSidebarSourceControl.vue'; import { hasPermission } from '@/rbac/permissions'; +import { useExternalHooks } from '@/composables/useExternalHooks'; export default defineComponent({ name: 'MainSidebar', @@ -130,11 +131,14 @@ export default defineComponent({ MainSidebarSourceControl, }, mixins: [genericHelpers, workflowHelpers, workflowRun, userHelpers, debounceHelper], - setup(props) { + setup(props, ctx) { + const externalHooks = useExternalHooks(); + return { + externalHooks, ...useMessage(), // eslint-disable-next-line @typescript-eslint/no-misused-promises - ...workflowRun.setup?.(props), + ...workflowRun.setup?.(props, ctx), }; }, data() { @@ -349,7 +353,7 @@ export default defineComponent({ async mounted() { this.basePath = this.rootStore.baseUrl; if (this.$refs.user) { - void this.$externalHooks().run('mainSidebar.mounted', { + void this.externalHooks.run('mainSidebar.mounted', { userRef: this.$refs.user as Element, }); } diff --git a/packages/editor-ui/src/components/Node.vue b/packages/editor-ui/src/components/Node.vue index de16549f0d..97bfbdb7f5 100644 --- a/packages/editor-ui/src/components/Node.vue +++ b/packages/editor-ui/src/components/Node.vue @@ -156,7 +156,6 @@ import { NOT_DUPLICATABE_NODE_TYPES, WAIT_TIME_UNLIMITED, } from '@/constants'; -import { externalHooks } from '@/mixins/externalHooks'; import { nodeBase } from '@/mixins/nodeBase'; import { nodeHelpers } from '@/mixins/nodeHelpers'; import { workflowHelpers } from '@/mixins/workflowHelpers'; @@ -187,14 +186,17 @@ import { useNodeTypesStore } from '@/stores/nodeTypes.store'; import { EnableNodeToggleCommand } from '@/models/history'; import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; import { type ContextMenuTarget, useContextMenu } from '@/composables/useContextMenu'; +import { useExternalHooks } from '@/composables/useExternalHooks'; export default defineComponent({ name: 'Node', setup() { const contextMenu = useContextMenu(); - return { contextMenu }; + const externalHooks = useExternalHooks(); + + return { contextMenu, externalHooks }; }, - mixins: [externalHooks, nodeBase, nodeHelpers, workflowHelpers, pinData, debounceHelper], + mixins: [nodeBase, nodeHelpers, workflowHelpers, pinData, debounceHelper], components: { TitledList, FontAwesomeIcon, diff --git a/packages/editor-ui/src/components/Node/NodeCreator/Modes/ActionsMode.vue b/packages/editor-ui/src/components/Node/NodeCreator/Modes/ActionsMode.vue index 11a7676ef6..321b44e541 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/Modes/ActionsMode.vue +++ b/packages/editor-ui/src/components/Node/NodeCreator/Modes/ActionsMode.vue @@ -16,7 +16,7 @@ import { } from '@/constants'; import { useUsersStore } from '@/stores/users.store'; -import { runExternalHook } from '@/utils/externalHooks'; +import { useExternalHooks } from '@/composables/useExternalHooks'; import { useActions } from '../composables/useActions'; import { useKeyboardNavigation } from '../composables/useKeyboardNavigation'; @@ -170,7 +170,7 @@ function trackActionsView() { trigger_action_count, }; - void runExternalHook('nodeCreateList.onViewActions', trackingPayload); + void useExternalHooks().run('nodeCreateList.onViewActions', trackingPayload); telemetry?.trackNodesPanel('nodeCreateList.onViewActions', trackingPayload); } @@ -191,7 +191,7 @@ function addHttpNode() { if (telemetry) setAddedNodeActionParameters(updateData); const app_identifier = actions.value[0].key; - void runExternalHook('nodeCreateList.onActionsCustmAPIClicked', { + void useExternalHooks().run('nodeCreateList.onActionsCustmAPIClicked', { app_identifier, }); telemetry?.trackNodesPanel('nodeCreateList.onActionsCustmAPIClicked', { app_identifier }); diff --git a/packages/editor-ui/src/components/Node/NodeCreator/composables/useActions.ts b/packages/editor-ui/src/components/Node/NodeCreator/composables/useActions.ts index 231d89ff02..5d510f18ef 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/composables/useActions.ts +++ b/packages/editor-ui/src/components/Node/NodeCreator/composables/useActions.ts @@ -26,7 +26,7 @@ import type { Telemetry } from '@/plugins/telemetry'; import { useNodeCreatorStore } from '@/stores/nodeCreator.store'; import { useWorkflowsStore } from '@/stores/workflows.store'; import { useNodeTypesStore } from '@/stores/nodeTypes.store'; -import { runExternalHook } from '@/utils/externalHooks'; +import { useExternalHooks } from '@/composables/useExternalHooks'; import { sortNodeCreateElements, transformNodeType } from '../utils'; @@ -255,7 +255,7 @@ export const useActions = () => { source_mode: rootView.toLowerCase(), resource: (action.value as INodeParameters).resource || '', }; - void runExternalHook('nodeCreateList.addAction', payload); + void useExternalHooks().run('nodeCreateList.addAction', payload); telemetry?.trackNodesPanel('nodeCreateList.addAction', payload); } diff --git a/packages/editor-ui/src/components/NodeDetailsView.vue b/packages/editor-ui/src/components/NodeDetailsView.vue index 9e2c95e0a5..2806417632 100644 --- a/packages/editor-ui/src/components/NodeDetailsView.vue +++ b/packages/editor-ui/src/components/NodeDetailsView.vue @@ -147,7 +147,6 @@ import type { import { jsonParse, NodeHelpers, NodeConnectionType } from 'n8n-workflow'; import type { IExecutionResponse, INodeUi, IUpdateInformation, TargetItem } from '@/Interface'; -import { externalHooks } from '@/mixins/externalHooks'; import { nodeHelpers } from '@/mixins/nodeHelpers'; import { workflowHelpers } from '@/mixins/workflowHelpers'; @@ -175,10 +174,11 @@ import { useUIStore } from '@/stores/ui.store'; import { useSettingsStore } from '@/stores/settings.store'; import { useDeviceSupport } from 'n8n-design-system/composables/useDeviceSupport'; import { useMessage } from '@/composables/useMessage'; +import { useExternalHooks } from '@/composables/useExternalHooks'; export default defineComponent({ name: 'NodeDetailsView', - mixins: [externalHooks, nodeHelpers, workflowHelpers, workflowActivate, pinData], + mixins: [nodeHelpers, workflowHelpers, workflowActivate, pinData], components: { NodeSettings, InputPanel, @@ -198,12 +198,15 @@ export default defineComponent({ default: false, }, }, - setup(props) { + setup(props, ctx) { + const externalHooks = useExternalHooks(); + return { + externalHooks, ...useDeviceSupport(), ...useMessage(), // eslint-disable-next-line @typescript-eslint/no-misused-promises - ...workflowActivate.setup?.(props), + ...workflowActivate.setup?.(props, ctx), }; }, data() { @@ -467,7 +470,7 @@ export default defineComponent({ this.avgInputRowHeight = 0; setTimeout(() => this.ndvStore.setNDVSessionId(), 0); - void this.$externalHooks().run('dataDisplay.nodeTypeChanged', { + void this.externalHooks.run('dataDisplay.nodeTypeChanged', { nodeSubtitle: this.getNodeSubtitle(node, this.activeNodeType, this.getCurrentWorkflow()), }); @@ -691,7 +694,7 @@ export default defineComponent({ this.ndvStore.setOutputPanelEditModeEnabled(false); } - await this.$externalHooks().run('dataDisplay.nodeEditingFinished'); + await this.externalHooks.run('dataDisplay.nodeEditingFinished'); this.$telemetry.track('User closed node modal', { node_type: this.activeNodeType ? this.activeNodeType.name : '', session_id: this.sessionId, diff --git a/packages/editor-ui/src/components/NodeExecuteButton.vue b/packages/editor-ui/src/components/NodeExecuteButton.vue index 175d610c32..1522052b54 100644 --- a/packages/editor-ui/src/components/NodeExecuteButton.vue +++ b/packages/editor-ui/src/components/NodeExecuteButton.vue @@ -39,6 +39,7 @@ import { useNDVStore } from '@/stores/ndv.store'; import { useNodeTypesStore } from '@/stores/nodeTypes.store'; import { useMessage } from '@/composables/useMessage'; import { useToast } from '@/composables/useToast'; +import { useExternalHooks } from '@/composables/useExternalHooks'; export default defineComponent({ inheritAttrs: false, @@ -68,12 +69,15 @@ export default defineComponent({ type: String, }, }, - setup(props) { + setup(props, ctx) { + const externalHooks = useExternalHooks(); + return { + externalHooks, ...useToast(), ...useMessage(), // eslint-disable-next-line @typescript-eslint/no-misused-promises - ...workflowRun.setup?.(props), + ...workflowRun.setup?.(props, ctx), }; }, computed: { @@ -241,7 +245,7 @@ export default defineComponent({ session_id: this.ndvStore.sessionId, }; this.$telemetry.track('User clicked execute node button', telemetryPayload); - await this.$externalHooks().run('nodeExecuteButton.onClick', telemetryPayload); + await this.externalHooks.run('nodeExecuteButton.onClick', telemetryPayload); await this.runWorkflow({ destinationNode: this.nodeName, diff --git a/packages/editor-ui/src/components/NodeSettings.vue b/packages/editor-ui/src/components/NodeSettings.vue index 7a17e9b3c7..53179a8bfd 100644 --- a/packages/editor-ui/src/components/NodeSettings.vue +++ b/packages/editor-ui/src/components/NodeSettings.vue @@ -201,7 +201,6 @@ import NodeSettingsTabs from '@/components/NodeSettingsTabs.vue'; import NodeWebhooks from '@/components/NodeWebhooks.vue'; import { get, set, unset } from 'lodash-es'; -import { externalHooks } from '@/mixins/externalHooks'; import { nodeHelpers } from '@/mixins/nodeHelpers'; import NodeExecuteButton from './NodeExecuteButton.vue'; @@ -215,10 +214,11 @@ import { RenameNodeCommand } from '@/models/history'; import useWorkflowsEEStore from '@/stores/workflows.ee.store'; import { useCredentialsStore } from '@/stores/credentials.store'; import type { EventBus } from 'n8n-design-system'; +import { useExternalHooks } from '@/composables/useExternalHooks'; export default defineComponent({ name: 'NodeSettings', - mixins: [externalHooks, nodeHelpers], + mixins: [nodeHelpers], components: { NodeTitle, NodeCredentials, @@ -227,6 +227,12 @@ export default defineComponent({ NodeWebhooks, NodeExecuteButton, }, + setup() { + const externalHooks = useExternalHooks(); + return { + externalHooks, + }; + }, computed: { ...mapStores( useHistoryStore, @@ -676,7 +682,7 @@ export default defineComponent({ this.updateNodeCredentialIssues(node); } - void this.$externalHooks().run('nodeSettings.credentialSelected', { updateInformation }); + void this.externalHooks.run('nodeSettings.credentialSelected', { updateInformation }); }, nameChanged(name: string) { if (this.node) { @@ -775,7 +781,7 @@ export default defineComponent({ } } - void this.$externalHooks().run('nodeSettings.valueChanged', { + void this.externalHooks.run('nodeSettings.valueChanged', { parameterPath, newValue, parameters: this.parameters, @@ -883,7 +889,7 @@ export default defineComponent({ this.workflowsStore.setNodeParameters(updateInformation); - void this.$externalHooks().run('nodeSettings.valueChanged', { + void this.externalHooks.run('nodeSettings.valueChanged', { parameterPath, newValue, parameters: this.parameters, diff --git a/packages/editor-ui/src/components/NodeSettingsTabs.vue b/packages/editor-ui/src/components/NodeSettingsTabs.vue index 17a7ec8e4d..51190365d2 100644 --- a/packages/editor-ui/src/components/NodeSettingsTabs.vue +++ b/packages/editor-ui/src/components/NodeSettingsTabs.vue @@ -10,7 +10,6 @@