chore(n8n Form Node): Incorporate design feedback for Custom HTML (#12817)

This commit is contained in:
Dana 2025-02-04 18:03:19 +01:00 committed by GitHub
parent b60011a180
commit ddc40ef7de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 106 additions and 24 deletions

View file

@ -6,13 +6,9 @@
<meta property="og:title" content="{{formTitle}}" />
<meta property="og:description" content="{{formDescriptionMetadata}}" />
<meta property="og:type" content="website" />
<meta property="og:image" content="https://raw.githubusercontent.com/n8n-io/n8n/80be10551eb081cb11bd8cab6c6ff89e44493d2c/assets/og_image.png?raw=true" />
<meta property="og:image" content="/static/og_image.png" />
<link rel='icon' type='image/png' href='https://n8n.io/favicon.ico' />
<link
href='https://fonts.googleapis.com/css?family=Open+Sans'
rel='stylesheet'
type='text/css'
/>
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
<title>{{formTitle}}</title>
<style>
*,
@ -25,7 +21,7 @@
body {
font-family:
Open Sans,
"Open Sans",
sans-serif;
font-weight: 400;
font-size: 12px;
@ -288,6 +284,60 @@
display: inline-block;
}
div.html {
text-align: left;
color: #555;
font-size: 14px;
}
div.html h1, div.html h2, div.html h3, div.html h4, div.html h5, div.html h6, div.html p, div.html ul, div.html ol, div.html a {
font-weight: 400;
font-style: normal;
margin-bottom: 8px;
}
div.html li {
margin-bottom: 8px;
margin-left: 24px;
}
div.html ul, div.html ol {
font-size: 14px;
display: flex;
flex-direction: column;
align-self: stretch;
line-height: normal;
}
div.html b {
font-weight: 600;
}
div.html h1 {
font-size: 28px;
line-height: 35px;
}
div.html h2 {
font-size: 20px;
line-height: 26px;
}
div.html h3 {
font-size: 16px;
line-height: 24px;
}
div.html h4 {
font-size: 14px;
line-height: 18px;
}
div.html h5 {
font-size: 12px;
}
div.html h6 {
font-size: 10px;
}
div.html p {
margin-bottom: 8px;
}
div.html a {
color: #FF6D5A;
font-size: 14px;
}
@media only screen and (max-width: 500px) {
body {
background-color: white;
@ -372,8 +422,9 @@
{{/if}}
{{#if isHtml}}
<div class="form-group">
<div class="form-group html">
{{{html}}}
<input type="hidden" id="{{id}}" name="{{id}}" value="{{html}}" />
</div>
{{/if}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -57,7 +57,7 @@ export const formFields: INodeProperties = {
name: 'values',
values: [
{
displayName: 'Field Label',
displayName: 'Field Name',
name: 'fieldLabel',
type: 'string',
default: '',
@ -66,7 +66,7 @@ export const formFields: INodeProperties = {
required: true,
displayOptions: {
hide: {
fieldType: ['hiddenField'],
fieldType: ['hiddenField', 'html'],
},
},
},
@ -120,6 +120,19 @@ export const formFields: INodeProperties = {
],
required: true,
},
{
displayName: 'Element Name',
name: 'elementName',
type: 'string',
default: '',
placeholder: 'e.g. content-section',
description: 'Optional field. It can be used to include the html in the output.',
displayOptions: {
show: {
fieldType: ['html'],
},
},
},
{
displayName: 'Placeholder',
name: 'placeholder',
@ -204,14 +217,16 @@ export const formFields: INodeProperties = {
},
},
{
displayName: 'HTML Template',
displayName: 'HTML',
name: 'html',
typeOptions: {
editor: 'htmlEditor',
},
type: 'string',
noDataExpression: true,
default: placeholder,
description: 'HTML template to render',
description: 'HTML elements to display on the form page',
hint: 'Does not accept <code>&lt;script&gt;</code>, <code>&lt;style&gt;</code> or <code>&lt;input&gt;</code> tags',
displayOptions: {
show: {
fieldType: ['html'],
@ -256,18 +271,6 @@ export const formFields: INodeProperties = {
},
},
},
{
displayName:
'Does not accept <code>&lt;style&gt;</code> <code>&lt;script&gt;</code> or <code>&lt;input&gt;</code> tags.',
name: 'htmlTips',
type: 'notice',
default: '',
displayOptions: {
show: {
fieldType: ['html'],
},
},
},
{
displayName: 'Required Field',
name: 'requiredField',

View file

@ -743,6 +743,22 @@ describe('prepareFormReturnItem', () => {
expect(result.json.formQueryParameters).toEqual(staticData);
});
it('should return html if field name is set', async () => {
mockContext.getBodyData.mockReturnValue({
data: { 'field-0': '<div>hi</div>', 'field-1': '<h1><haha/hi>' },
files: {},
});
const formFields = [
{ fieldLabel: '', elementName: 'greeting', fieldType: 'html' },
{ fieldLabel: '', elementName: '', fieldType: 'html' },
];
const result = await prepareFormReturnItem(mockContext, formFields, 'production');
expect(result.json.greeting).toBe('<div>hi</div>');
expect(result.json.formMode).toBe('production');
});
});
describe('resolveRawData', () => {

View file

@ -50,6 +50,10 @@ export function sanitizeHtml(text: string) {
'pre',
'span',
'br',
'ul',
'ol',
'li',
'p',
],
allowedAttributes: {
a: ['href', 'target', 'rel'],
@ -280,6 +284,13 @@ export async function prepareFormReturnItem(
continue;
}
if (field.fieldType === 'html') {
if (field.elementName) {
returnItem.json[field.elementName as string] = value;
}
continue;
}
if (field.fieldType === 'number') {
value = Number(value);
}

View file

@ -2677,6 +2677,7 @@ export interface ResourceMapperField {
export type FormFieldsParameter = Array<{
fieldLabel: string;
elementName?: string;
fieldType?: string;
requiredField?: boolean;
fieldOptions?: { values: Array<{ option: string }> };