mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
feat(n8n Form Trigger Node, Chat Trigger Node): Allow to customize form and chat css (#13506)
This commit is contained in:
@@ -12,6 +12,7 @@ import type {
|
||||
INodeProperties,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { cssVariables } from './constants';
|
||||
import { validateAuth } from './GenericFunctions';
|
||||
import { createPage } from './templates';
|
||||
import type { LoadPreviousSessionChatOption } from './types';
|
||||
@@ -378,6 +379,29 @@ export class ChatTrigger extends Node {
|
||||
placeholder: 'e.g. Welcome',
|
||||
description: 'Shown at the top of the chat',
|
||||
},
|
||||
{
|
||||
displayName: 'Custom Chat Styling',
|
||||
name: 'customCss',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
rows: 10,
|
||||
editor: 'cssEditor',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/mode': ['hostedChat'],
|
||||
},
|
||||
},
|
||||
default: `
|
||||
${cssVariables}
|
||||
|
||||
/* You can override any class styles, too. Right-click inspect in Chat UI to find class to override. */
|
||||
.chat-message {
|
||||
max-width: 50%;
|
||||
}
|
||||
`.trim(),
|
||||
description: 'Override default styling of the public chat interface with CSS',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -466,6 +490,7 @@ export class ChatTrigger extends Node {
|
||||
title?: string;
|
||||
allowFileUploads?: boolean;
|
||||
allowedFilesMimeTypes?: string;
|
||||
customCss?: string;
|
||||
};
|
||||
|
||||
const req = ctx.getRequestObject();
|
||||
@@ -517,6 +542,7 @@ export class ChatTrigger extends Node {
|
||||
authentication,
|
||||
allowFileUploads: options.allowFileUploads,
|
||||
allowedFilesMimeTypes: options.allowedFilesMimeTypes,
|
||||
customCss: options.customCss,
|
||||
});
|
||||
|
||||
res.status(200).send(page).end();
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
// CSS Variables are defined in `@n8n/chat/src/css/_tokens.scss`
|
||||
export const cssVariables = `
|
||||
:root {
|
||||
/* Colors */
|
||||
--chat--color-primary: #e74266;
|
||||
--chat--color-primary-shade-50: #db4061;
|
||||
--chat--color-primary-shade-100: #cf3c5c;
|
||||
--chat--color-secondary: #20b69e;
|
||||
--chat--color-secondary-shade-50: #1ca08a;
|
||||
--chat--color-white: #ffffff;
|
||||
--chat--color-light: #f2f4f8;
|
||||
--chat--color-light-shade-50: #e6e9f1;
|
||||
--chat--color-light-shade-100: #c2c5cc;
|
||||
--chat--color-medium: #d2d4d9;
|
||||
--chat--color-dark: #101330;
|
||||
--chat--color-disabled: #777980;
|
||||
--chat--color-typing: #404040;
|
||||
|
||||
/* Base Layout */
|
||||
--chat--spacing: 1rem;
|
||||
--chat--border-radius: 0.25rem;
|
||||
--chat--transition-duration: 0.15s;
|
||||
--chat--font-family: (
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
'Segoe UI',
|
||||
Roboto,
|
||||
Oxygen-Sans,
|
||||
Ubuntu,
|
||||
Cantarell,
|
||||
'Helvetica Neue',
|
||||
sans-serif
|
||||
);
|
||||
|
||||
/* Window Dimensions */
|
||||
--chat--window--width: 400px;
|
||||
--chat--window--height: 600px;
|
||||
--chat--window--bottom: var(--chat--spacing);
|
||||
--chat--window--right: var(--chat--spacing);
|
||||
--chat--window--z-index: 9999;
|
||||
--chat--window--border: 1px solid var(--chat--color-light-shade-50);
|
||||
--chat--window--border-radius: var(--chat--border-radius);
|
||||
--chat--window--margin-bottom: var(--chat--spacing);
|
||||
|
||||
/* Header Styles */
|
||||
--chat--header-height: auto;
|
||||
--chat--header--padding: var(--chat--spacing);
|
||||
--chat--header--background: var(--chat--color-dark);
|
||||
--chat--header--color: var(--chat--color-light);
|
||||
--chat--header--border-top: none;
|
||||
--chat--header--border-bottom: none;
|
||||
--chat--header--border-left: none;
|
||||
--chat--header--border-right: none;
|
||||
--chat--heading--font-size: 2em;
|
||||
--chat--subtitle--font-size: inherit;
|
||||
--chat--subtitle--line-height: 1.8;
|
||||
|
||||
/* Message Styles */
|
||||
--chat--message--font-size: 1rem;
|
||||
--chat--message--padding: var(--chat--spacing);
|
||||
--chat--message--border-radius: var(--chat--border-radius);
|
||||
--chat--message-line-height: 1.5;
|
||||
--chat--message--margin-bottom: calc(var(--chat--spacing) * 1);
|
||||
--chat--message--bot--background: var(--chat--color-white);
|
||||
--chat--message--bot--color: var(--chat--color-dark);
|
||||
--chat--message--bot--border: none;
|
||||
--chat--message--user--background: var(--chat--color-secondary);
|
||||
--chat--message--user--color: var(--chat--color-white);
|
||||
--chat--message--user--border: none;
|
||||
--chat--message--pre--background: rgba(0, 0, 0, 0.05);
|
||||
--chat--messages-list--padding: var(--chat--spacing);
|
||||
|
||||
/* Toggle Button */
|
||||
--chat--toggle--size: 64px;
|
||||
--chat--toggle--width: var(--chat--toggle--size);
|
||||
--chat--toggle--height: var(--chat--toggle--size);
|
||||
--chat--toggle--border-radius: 50%;
|
||||
--chat--toggle--background: var(--chat--color-primary);
|
||||
--chat--toggle--hover--background: var(--chat--color-primary-shade-50);
|
||||
--chat--toggle--active--background: var(--chat--color-primary-shade-100);
|
||||
--chat--toggle--color: var(--chat--color-white);
|
||||
|
||||
/* Input Area */
|
||||
--chat--textarea--height: 50px;
|
||||
--chat--textarea--max-height: 30rem;
|
||||
--chat--input--font-size: inherit;
|
||||
--chat--input--border: 0;
|
||||
--chat--input--border-radius: 0;
|
||||
--chat--input--padding: 0.8rem;
|
||||
--chat--input--background: var(--chat--color-white);
|
||||
--chat--input--text-color: initial;
|
||||
--chat--input--line-height: 1.5;
|
||||
--chat--input--placeholder--font-size: var(--chat--input--font-size);
|
||||
--chat--input--border-active: 0;
|
||||
--chat--input--left--panel--width: 2rem;
|
||||
|
||||
/* Button Styles */
|
||||
--chat--button--color: var(--chat--color-light);
|
||||
--chat--button--background: var(--chat--color-primary);
|
||||
--chat--button--padding: calc(var(--chat--spacing) * 1 / 2) var(--chat--spacing);
|
||||
--chat--button--border-radius: var(--chat--border-radius);
|
||||
--chat--button--hover--color: var(--chat--color-light);
|
||||
--chat--button--hover--background: var(--chat--color-primary-shade-50);
|
||||
--chat--close--button--color-hover: var(--chat--color-primary);
|
||||
|
||||
/* Send and File Buttons */
|
||||
--chat--input--send--button--background: var(--chat--color-white);
|
||||
--chat--input--send--button--color: var(--chat--color-light);
|
||||
--chat--input--send--button--background-hover: var(--chat--color-primary-shade-50);
|
||||
--chat--input--send--button--color-hover: var(--chat--color-secondary-shade-50);
|
||||
--chat--input--file--button--background: var(--chat--color-white);
|
||||
--chat--input--file--button--color: var(--chat--color-secondary);
|
||||
--chat--input--file--button--background-hover: var(--chat--input--file--button--background);
|
||||
--chat--input--file--button--color-hover: var(--chat--color-secondary-shade-50);
|
||||
--chat--files-spacing: 0.25rem;
|
||||
|
||||
/* Body and Footer */
|
||||
--chat--body--background: var(--chat--color-light);
|
||||
--chat--footer--background: var(--chat--color-light);
|
||||
--chat--footer--color: var(--chat--color-dark);
|
||||
}
|
||||
`;
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { AuthenticationChatOption, LoadPreviousSessionChatOption } from './types';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
|
||||
import type { AuthenticationChatOption, LoadPreviousSessionChatOption } from './types';
|
||||
export function createPage({
|
||||
instanceId,
|
||||
webhookUrl,
|
||||
@@ -10,6 +11,7 @@ export function createPage({
|
||||
authentication,
|
||||
allowFileUploads,
|
||||
allowedFilesMimeTypes,
|
||||
customCss,
|
||||
}: {
|
||||
instanceId: string;
|
||||
webhookUrl?: string;
|
||||
@@ -23,6 +25,7 @@ export function createPage({
|
||||
authentication: AuthenticationChatOption;
|
||||
allowFileUploads?: boolean;
|
||||
allowedFilesMimeTypes?: string;
|
||||
customCss?: string;
|
||||
}) {
|
||||
const validAuthenticationOptions: AuthenticationChatOption[] = [
|
||||
'none',
|
||||
@@ -41,6 +44,11 @@ export function createPage({
|
||||
const sanitizedShowWelcomeScreen = !!showWelcomeScreen;
|
||||
const sanitizedAllowFileUploads = !!allowFileUploads;
|
||||
const sanitizedAllowedFilesMimeTypes = allowedFilesMimeTypes?.toString() ?? '';
|
||||
const sanitizedCustomCss = sanitizeHtml(`<style>${customCss?.toString() ?? ''}</style>`, {
|
||||
allowedTags: ['style'],
|
||||
allowedAttributes: false,
|
||||
});
|
||||
|
||||
const sanitizedLoadPreviousSession = validLoadPreviousSessionOptions.includes(
|
||||
loadPreviousSession as LoadPreviousSessionChatOption,
|
||||
)
|
||||
@@ -63,6 +71,7 @@ export function createPage({
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
${sanitizedCustomCss}
|
||||
</head>
|
||||
<body>
|
||||
<script type="module">
|
||||
|
||||
@@ -130,6 +130,7 @@
|
||||
"@types/mime-types": "^2.1.0",
|
||||
"@types/pg": "^8.11.6",
|
||||
"@types/temp": "^0.9.1",
|
||||
"@types/sanitize-html": "^2.11.0",
|
||||
"n8n-core": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -183,6 +184,7 @@
|
||||
"pdf-parse": "1.1.1",
|
||||
"pg": "8.12.0",
|
||||
"redis": "4.6.12",
|
||||
"sanitize-html": "2.12.1",
|
||||
"sqlite3": "5.1.7",
|
||||
"temp": "0.9.4",
|
||||
"tmp-promise": "3.0.3",
|
||||
|
||||
Reference in New Issue
Block a user