refactor(editor): Migrate NodeWebhooks to Composition API (no-changelog) (#10710)
Some checks failed
Test Master / install-and-build (push) Has been cancelled
Benchmark Docker Image CI / build (push) Has been cancelled
Test Master / Unit tests (18.x) (push) Has been cancelled
Test Master / Unit tests (20.x) (push) Has been cancelled
Test Master / Unit tests (22.4) (push) Has been cancelled
Test Master / Lint (push) Has been cancelled
Test Master / Notify Slack on failure (push) Has been cancelled

This commit is contained in:
Alex Grozav 2024-09-06 16:12:05 +03:00 committed by GitHub
parent e4c9035915
commit 6ea0856085
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 154 additions and 152 deletions

View file

@ -1025,7 +1025,7 @@ onBeforeUnmount(() => {
" "
/> />
<div v-show="openPanel === 'params'"> <div v-show="openPanel === 'params'">
<NodeWebhooks :node="node" :node-type="nodeType" /> <NodeWebhooks :node="node" :node-type-description="nodeType" />
<ParameterInputList <ParameterInputList
v-if="nodeValuesInitialized" v-if="nodeValuesInitialized"

View file

@ -1,7 +1,5 @@
<script lang="ts"> <script lang="ts" setup>
import type { INodeTypeDescription, IWebhookDescription } from 'n8n-workflow'; import type { INodeTypeDescription, IWebhookDescription } from 'n8n-workflow';
import { defineComponent } from 'vue';
import { useToast } from '@/composables/useToast'; import { useToast } from '@/composables/useToast';
import { import {
CHAT_TRIGGER_NODE_TYPE, CHAT_TRIGGER_NODE_TYPE,
@ -12,159 +10,163 @@ import {
import { useClipboard } from '@/composables/useClipboard'; import { useClipboard } from '@/composables/useClipboard';
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers'; import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import type { INodeUi } from '@/Interface';
import { computed, ref, watch } from 'vue';
import { useI18n } from '@/composables/useI18n';
import { useTelemetry } from '@/composables/useTelemetry';
export default defineComponent({ const props = defineProps<{
name: 'NodeWebhooks', node: INodeUi;
props: [ nodeTypeDescription: INodeTypeDescription | null;
'node', // NodeUi }>();
'nodeType', // INodeTypeDescription
],
setup() {
const router = useRouter();
const clipboard = useClipboard();
const workflowHelpers = useWorkflowHelpers({ router });
return {
clipboard,
workflowHelpers,
...useToast(),
};
},
data() {
return {
isMinimized: this.nodeType && !OPEN_URL_PANEL_TRIGGER_NODE_TYPES.includes(this.nodeType.name),
showUrlFor: 'test',
};
},
computed: {
isProductionOnly(): boolean {
return this.nodeType && PRODUCTION_ONLY_TRIGGER_NODE_TYPES.includes(this.nodeType.name);
},
urlOptions(): Array<{ label: string; value: string }> {
return [
...(this.isProductionOnly ? [] : [{ label: this.baseText.testUrl, value: 'test' }]),
{
label: this.baseText.productionUrl,
value: 'production',
},
];
},
visibleWebhookUrls(): IWebhookDescription[] {
return this.webhooksNode.filter((webhook) => {
if (typeof webhook.ndvHideUrl === 'string') {
return !this.workflowHelpers.getWebhookExpressionValue(webhook, 'ndvHideUrl');
}
return !webhook.ndvHideUrl; const router = useRouter();
}); const clipboard = useClipboard();
}, const workflowHelpers = useWorkflowHelpers({ router });
webhooksNode(): IWebhookDescription[] { const toast = useToast();
if (this.nodeType === null || this.nodeType.webhooks === undefined) { const i18n = useI18n();
return []; const telemetry = useTelemetry();
}
return (this.nodeType as INodeTypeDescription).webhooks!.filter( const isMinimized = ref(
(webhookData) => webhookData.restartWebhook !== true, props.nodeTypeDescription &&
); !OPEN_URL_PANEL_TRIGGER_NODE_TYPES.includes(props.nodeTypeDescription.name),
}, );
baseText() { const showUrlFor = ref('test');
const nodeType = this.nodeType.name;
switch (nodeType) {
case CHAT_TRIGGER_NODE_TYPE:
return {
toggleTitle: this.$locale.baseText('nodeWebhooks.webhookUrls.chatTrigger'),
clickToDisplay: this.$locale.baseText(
'nodeWebhooks.clickToDisplayWebhookUrls.formTrigger',
),
clickToHide: this.$locale.baseText('nodeWebhooks.clickToHideWebhookUrls.chatTrigger'),
clickToCopy: this.$locale.baseText('nodeWebhooks.clickToCopyWebhookUrls.chatTrigger'),
testUrl: this.$locale.baseText('nodeWebhooks.testUrl'),
productionUrl: this.$locale.baseText('nodeWebhooks.productionUrl'),
copyTitle: this.$locale.baseText('nodeWebhooks.showMessage.title.chatTrigger'),
copyMessage: this.$locale.baseText('nodeWebhooks.showMessage.message.chatTrigger'),
};
case FORM_TRIGGER_NODE_TYPE: const isProductionOnly = computed(() => {
return { return (
toggleTitle: this.$locale.baseText('nodeWebhooks.webhookUrls.formTrigger'), props.nodeTypeDescription &&
clickToDisplay: this.$locale.baseText( PRODUCTION_ONLY_TRIGGER_NODE_TYPES.includes(props.nodeTypeDescription.name)
'nodeWebhooks.clickToDisplayWebhookUrls.formTrigger', );
),
clickToHide: this.$locale.baseText('nodeWebhooks.clickToHideWebhookUrls.formTrigger'),
clickToCopy: this.$locale.baseText('nodeWebhooks.clickToCopyWebhookUrls.formTrigger'),
testUrl: this.$locale.baseText('nodeWebhooks.testUrl'),
productionUrl: this.$locale.baseText('nodeWebhooks.productionUrl'),
copyTitle: this.$locale.baseText('nodeWebhooks.showMessage.title.formTrigger'),
copyMessage: this.$locale.baseText('nodeWebhooks.showMessage.message.formTrigger'),
};
default:
return {
toggleTitle: this.$locale.baseText('nodeWebhooks.webhookUrls'),
clickToDisplay: this.$locale.baseText('nodeWebhooks.clickToDisplayWebhookUrls'),
clickToHide: this.$locale.baseText('nodeWebhooks.clickToHideWebhookUrls'),
clickToCopy: this.$locale.baseText('nodeWebhooks.clickToCopyWebhookUrls'),
testUrl: this.$locale.baseText('nodeWebhooks.testUrl'),
productionUrl: this.$locale.baseText('nodeWebhooks.productionUrl'),
copyTitle: this.$locale.baseText('nodeWebhooks.showMessage.title'),
copyMessage: undefined,
};
}
},
},
watch: {
node() {
this.isMinimized = !OPEN_URL_PANEL_TRIGGER_NODE_TYPES.includes(this.nodeType.name);
},
},
methods: {
copyWebhookUrl(webhookData: IWebhookDescription): void {
const webhookUrl = this.getWebhookUrlDisplay(webhookData);
void this.clipboard.copy(webhookUrl);
this.showMessage({
title: this.baseText.copyTitle,
message: this.baseText.copyMessage,
type: 'success',
});
this.$telemetry.track('User copied webhook URL', {
pane: 'parameters',
type: `${this.showUrlFor} url`,
});
},
getWebhookUrlDisplay(webhookData: IWebhookDescription): string {
if (this.node) {
return this.workflowHelpers.getWebhookUrl(
webhookData,
this.node,
this.isProductionOnly ? 'production' : this.showUrlFor,
);
}
return '';
},
isWebhookMethodVisible(webhook: IWebhookDescription): boolean {
try {
const method = this.workflowHelpers.getWebhookExpressionValue(webhook, 'httpMethod', false);
if (Array.isArray(method) && method.length !== 1) {
return false;
}
} catch (error) {}
if (typeof webhook.ndvHideMethod === 'string') {
return !this.workflowHelpers.getWebhookExpressionValue(webhook, 'ndvHideMethod');
}
return !webhook.ndvHideMethod;
},
getWebhookHttpMethod(webhook: IWebhookDescription): string {
const method = this.workflowHelpers.getWebhookExpressionValue(webhook, 'httpMethod', false);
if (Array.isArray(method)) {
return method[0];
}
return method;
},
},
}); });
const urlOptions = computed(() => [
...(isProductionOnly.value ? [] : [{ label: baseText.value.testUrl, value: 'test' }]),
{
label: baseText.value.productionUrl,
value: 'production',
},
]);
const visibleWebhookUrls = computed(() => {
return webhooksNode.value.filter((webhook) => {
if (typeof webhook.ndvHideUrl === 'string') {
return !workflowHelpers.getWebhookExpressionValue(webhook, 'ndvHideUrl');
}
return !webhook.ndvHideUrl;
});
});
const webhooksNode = computed(() => {
if (props.nodeTypeDescription?.webhooks === undefined) {
return [];
}
return props.nodeTypeDescription.webhooks.filter(
(webhookData) => webhookData.restartWebhook !== true,
);
});
const baseText = computed(() => {
const nodeType = props.nodeTypeDescription?.name;
switch (nodeType) {
case CHAT_TRIGGER_NODE_TYPE:
return {
toggleTitle: i18n.baseText('nodeWebhooks.webhookUrls.chatTrigger'),
clickToDisplay: i18n.baseText('nodeWebhooks.clickToDisplayWebhookUrls.formTrigger'),
clickToHide: i18n.baseText('nodeWebhooks.clickToHideWebhookUrls.chatTrigger'),
clickToCopy: i18n.baseText('nodeWebhooks.clickToCopyWebhookUrls.chatTrigger'),
testUrl: i18n.baseText('nodeWebhooks.testUrl'),
productionUrl: i18n.baseText('nodeWebhooks.productionUrl'),
copyTitle: i18n.baseText('nodeWebhooks.showMessage.title.chatTrigger'),
copyMessage: i18n.baseText('nodeWebhooks.showMessage.message.chatTrigger'),
};
case FORM_TRIGGER_NODE_TYPE:
return {
toggleTitle: i18n.baseText('nodeWebhooks.webhookUrls.formTrigger'),
clickToDisplay: i18n.baseText('nodeWebhooks.clickToDisplayWebhookUrls.formTrigger'),
clickToHide: i18n.baseText('nodeWebhooks.clickToHideWebhookUrls.formTrigger'),
clickToCopy: i18n.baseText('nodeWebhooks.clickToCopyWebhookUrls.formTrigger'),
testUrl: i18n.baseText('nodeWebhooks.testUrl'),
productionUrl: i18n.baseText('nodeWebhooks.productionUrl'),
copyTitle: i18n.baseText('nodeWebhooks.showMessage.title.formTrigger'),
copyMessage: i18n.baseText('nodeWebhooks.showMessage.message.formTrigger'),
};
default:
return {
toggleTitle: i18n.baseText('nodeWebhooks.webhookUrls'),
clickToDisplay: i18n.baseText('nodeWebhooks.clickToDisplayWebhookUrls'),
clickToHide: i18n.baseText('nodeWebhooks.clickToHideWebhookUrls'),
clickToCopy: i18n.baseText('nodeWebhooks.clickToCopyWebhookUrls'),
testUrl: i18n.baseText('nodeWebhooks.testUrl'),
productionUrl: i18n.baseText('nodeWebhooks.productionUrl'),
copyTitle: i18n.baseText('nodeWebhooks.showMessage.title'),
copyMessage: undefined,
};
}
});
function copyWebhookUrl(webhookData: IWebhookDescription): void {
const webhookUrl = getWebhookUrlDisplay(webhookData);
void clipboard.copy(webhookUrl);
toast.showMessage({
title: baseText.value.copyTitle,
message: baseText.value.copyMessage,
type: 'success',
});
telemetry.track('User copied webhook URL', {
pane: 'parameters',
type: `${showUrlFor.value} url`,
});
}
function getWebhookUrlDisplay(webhookData: IWebhookDescription): string {
if (props.node) {
return workflowHelpers.getWebhookUrl(
webhookData,
props.node,
isProductionOnly.value ? 'production' : showUrlFor.value,
);
}
return '';
}
function isWebhookMethodVisible(webhook: IWebhookDescription): boolean {
try {
const method = workflowHelpers.getWebhookExpressionValue(webhook, 'httpMethod', false);
if (Array.isArray(method) && method.length !== 1) {
return false;
}
} catch (error) {}
if (typeof webhook.ndvHideMethod === 'string') {
return !workflowHelpers.getWebhookExpressionValue(webhook, 'ndvHideMethod');
}
return !webhook.ndvHideMethod;
}
function getWebhookHttpMethod(webhook: IWebhookDescription): string {
const method = workflowHelpers.getWebhookExpressionValue(webhook, 'httpMethod', false);
if (Array.isArray(method)) {
return method[0];
}
return method;
}
watch(
() => props.node,
() => {
isMinimized.value =
props.nodeTypeDescription &&
!OPEN_URL_PANEL_TRIGGER_NODE_TYPES.includes(props.nodeTypeDescription.name);
},
);
</script> </script>
<template> <template>