feat(n8n Form Node): Respond with Text (#12979)

This commit is contained in:
Dana
2025-02-04 18:35:25 +01:00
committed by GitHub
parent ddc40ef7de
commit 182fc150be
6 changed files with 276 additions and 175 deletions

View File

@@ -5,6 +5,7 @@ import type {
INodeProperties,
INodeTypeDescription,
IWebhookFunctions,
IWebhookResponseData,
NodeTypeAndVersion,
} from 'n8n-workflow';
import {
@@ -15,12 +16,13 @@ import {
FORM_TRIGGER_NODE_TYPE,
tryToParseJsonToFormFields,
NodeConnectionType,
WAIT_NODE_TYPE,
WAIT_INDEFINITELY,
} from 'n8n-workflow';
import { renderFormCompletion } from './formCompletionUtils';
import { renderFormNode } from './formNodeUtils';
import { formDescription, formFields, formTitle } from '../Form/common.descriptions';
import { prepareFormReturnItem, renderForm, resolveRawData } from '../Form/utils';
import { prepareFormReturnItem, resolveRawData } from '../Form/utils';
export const formFieldsProperties: INodeProperties[] = [
{
@@ -113,6 +115,11 @@ const completionProperties = updateDisplayOptions(
value: 'redirect',
description: 'Redirect the user to a URL',
},
{
name: 'Show Text',
value: 'showText',
description: 'Display simple text or HTML',
},
],
},
{
@@ -154,6 +161,22 @@ const completionProperties = updateDisplayOptions(
},
},
},
{
displayName: 'Text',
name: 'responseText',
type: 'string',
displayOptions: {
show: {
respondWith: ['showText'],
},
},
typeOptions: {
rows: 2,
},
default: '',
placeholder: 'e.g. Thanks for filling the form',
description: 'The text to display on the page. Use HTML to show a customized web page.',
},
{
displayName: 'Options',
name: 'options',
@@ -235,7 +258,7 @@ export class Form extends Node {
],
};
async webhook(context: IWebhookFunctions) {
async webhook(context: IWebhookFunctions): Promise<IWebhookResponseData> {
const res = context.getResponseObject();
const operation = context.getNodeParameter('operation', '') as string;
@@ -280,36 +303,7 @@ export class Form extends Node {
const method = context.getRequestObject().method;
if (operation === 'completion' && method === 'GET') {
const completionTitle = context.getNodeParameter('completionTitle', '') as string;
const completionMessage = context.getNodeParameter('completionMessage', '') as string;
const redirectUrl = context.getNodeParameter('redirectUrl', '') as string;
const options = context.getNodeParameter('options', {}) as { formTitle: string };
if (redirectUrl) {
res.send(
`<html><head><meta http-equiv="refresh" content="0; url=${redirectUrl}"></head></html>`,
);
return { noWebhookResponse: true };
}
let title = options.formTitle;
if (!title) {
title = context.evaluateExpression(
`{{ $('${trigger?.name}').params.formTitle }}`,
) as string;
}
const appendAttribution = context.evaluateExpression(
`{{ $('${trigger?.name}').params.options?.appendAttribution === false ? false : true }}`,
) as boolean;
res.render('form-trigger-completion', {
title: completionTitle,
message: completionMessage,
formTitle: title,
appendAttribution,
});
return { noWebhookResponse: true };
return await renderFormCompletion(context, res, trigger);
}
if (operation === 'completion' && method === 'POST') {
@@ -319,68 +313,7 @@ export class Form extends Node {
}
if (method === 'GET') {
const options = context.getNodeParameter('options', {}) as {
formTitle: string;
formDescription: string;
buttonLabel: string;
};
let title = options.formTitle;
if (!title) {
title = context.evaluateExpression(
`{{ $('${trigger?.name}').params.formTitle }}`,
) as string;
}
let description = options.formDescription;
if (!description) {
description = context.evaluateExpression(
`{{ $('${trigger?.name}').params.formDescription }}`,
) as string;
}
let buttonLabel = options.buttonLabel;
if (!buttonLabel) {
buttonLabel =
(context.evaluateExpression(
`{{ $('${trigger?.name}').params.options?.buttonLabel }}`,
) as string) || 'Submit';
}
const responseMode = 'onReceived';
let redirectUrl;
const connectedNodes = context.getChildNodes(context.getNode().name);
const hasNextPage = connectedNodes.some(
(node) => !node.disabled && (node.type === FORM_NODE_TYPE || node.type === WAIT_NODE_TYPE),
);
if (hasNextPage) {
redirectUrl = context.evaluateExpression('{{ $execution.resumeFormUrl }}') as string;
}
const appendAttribution = context.evaluateExpression(
`{{ $('${trigger?.name}').params.options?.appendAttribution === false ? false : true }}`,
) as boolean;
renderForm({
context,
res,
formTitle: title,
formDescription: description,
formFields: fields,
responseMode,
mode,
redirectUrl,
appendAttribution,
buttonLabel,
});
return {
noWebhookResponse: true,
};
return await renderFormNode(context, res, trigger, fields, mode);
}
let useWorkflowTimezone = context.evaluateExpression(