Skip to content

Commit

Permalink
Text editor for custom workflow templates (#5654)
Browse files Browse the repository at this point in the history
* add first version of text editor

* add new editor to email body

* fix line height

* remove not needed styles

* allow adding html tags + small refactoring

* fix error when input is empty

* styling of add variable dropdown

* fix bg on focus

* small design fixes

* improve design

* show error message for no input

* text editor only for email body

* remove test button

* code clean up

* code clean up

* code clean up

* fix that added variables weren't saved

* fix import

* first version of editor

* connect reminder body of form with new editor

* add pencile for link-editor

* remove TreeViewPlugin

* clean up css file

* code clean up

* add text indent for list

* improve editor design

* fix style

* slow resizing of editor

* fix that new data was removed when leaving tab

* dont allow italic and bold at same time

* code clean up

* fix type error

* code clean up

* code clean up

* remove text if changed from SMS to email or other way around

* add add variable dropdown

* show error message if email body is empty

* add white-space pre-wrap

* fix import

* prettier

* fix add variable dropdown for mobile

* move dependencies to correct package.json file

* remove html-to-text

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
  • Loading branch information
CarinaWolli and CarinaWolli authored Nov 25, 2022
1 parent 3137a18 commit 2de3e7f
Show file tree
Hide file tree
Showing 20 changed files with 1,207 additions and 56 deletions.
3 changes: 2 additions & 1 deletion apps/web/public/static/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -1375,5 +1375,6 @@
"route_to": "Route to",
"test_preview_description": "Test your routing form without submitting any data",
"test_routing": "Test Routing",
"booking_limit_reached":"Booking Limit for this event type has been reached"
"booking_limit_reached":"Booking Limit for this event type has been reached",
"fill_this_field": "Please fill in this field"
}
25 changes: 19 additions & 6 deletions packages/features/ee/workflows/components/AddVariablesDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Dropdown, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Icon } from "@calcom/ui";

interface IAddVariablesDropdown {
addVariable: (isEmailSubject: boolean, variable: string) => void;
isEmailSubject: boolean;
addVariable: (variable: string, isEmailSubject?: boolean) => void;
isEmailSubject?: boolean;
isTextEditor?: boolean;
}

const variables = [
Expand All @@ -23,9 +24,21 @@ export const AddVariablesDropdown = (props: IAddVariablesDropdown) => {
return (
<Dropdown>
<DropdownMenuTrigger className="pt-[6px] focus:bg-gray-50">
<div className="flex items-center ">
{t("add_variable")}
<Icon.FiChevronDown className="ml-1 h-4 w-4" />
<div className="items-center ">
{props.isTextEditor ? (
<>
<div className="hidden sm:flex">
{t("add_variable")}
<Icon.FiChevronDown className="ml-1 h-4 w-4" />
</div>
<div className="block sm:hidden">+</div>
</>
) : (
<div className="flex">
{t("add_variable")}
<Icon.FiChevronDown className="ml-1 h-4 w-4" />
</div>
)}
</div>
</DropdownMenuTrigger>
<DropdownMenuContent className="h-40 overflow-scroll">
Expand All @@ -39,7 +52,7 @@ export const AddVariablesDropdown = (props: IAddVariablesDropdown) => {
key={variable}
type="button"
className="w-full px-4 py-2"
onClick={() => props.addVariable(props.isEmailSubject, t(`${variable}_workflow`))}>
onClick={() => props.addVariable(t(`${variable}_workflow`), props.isEmailSubject)}>
<div className="sm:grid sm:grid-cols-2">
<div className="mr-3 text-left md:col-span-1">
{`{${t(`${variable}_workflow`).toUpperCase().replace(/ /g, "_")}}`}
Expand Down
69 changes: 69 additions & 0 deletions packages/features/ee/workflows/components/TextEditor/Editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { CodeHighlightNode, CodeNode } from "@lexical/code";
import { AutoLinkNode, LinkNode } from "@lexical/link";
import { ListItemNode, ListNode } from "@lexical/list";
import { TRANSFORMERS } from "@lexical/markdown";
import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
import { LexicalComposer } from "@lexical/react/LexicalComposer";
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin";
import { ListPlugin } from "@lexical/react/LexicalListPlugin";
import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
import { TableCellNode, TableNode, TableRowNode } from "@lexical/table";
import { UseFormReturn } from "react-hook-form";

import { FormValues } from "../../pages/workflow";
import ExampleTheme from "./ExampleTheme";
import AutoLinkPlugin from "./plugins/AutoLinkPlugin";
import ToolbarPlugin from "./plugins/ToolbarPlugin";
import "./stylesEditor.css";

export type TextEditorProps = {
form: UseFormReturn<FormValues>;
stepNumber: number;
};

const editorConfig = {
// The editor theme
theme: ExampleTheme,
// Handling of errors during update
onError(error: any) {
throw error;
},
namespace: "",
// Any custom nodes go here
nodes: [
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
CodeHighlightNode,
TableNode,
TableCellNode,
TableRowNode,
AutoLinkNode,
LinkNode,
],
};

export default function Editor(props: TextEditorProps) {
return (
<div className="editor">
<LexicalComposer initialConfig={editorConfig}>
<div className="editor-container">
<ToolbarPlugin form={props.form} stepNumber={props.stepNumber} />
<div className="editor-inner">
<RichTextPlugin contentEditable={<ContentEditable className="editor-input" />} placeholder="" />
<AutoFocusPlugin />
<ListPlugin />
<LinkPlugin />
<AutoLinkPlugin />
<MarkdownShortcutPlugin transformers={TRANSFORMERS} />
</div>
</div>
</LexicalComposer>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const exampleTheme = {
placeholder: "editor-placeholder",
paragraph: "editor-paragraph",
heading: {
h1: "editor-heading-h1",
h2: "editor-heading-h2",
},
list: {
nested: {
listitem: "editor-nested-listitem",
},
ol: "editor-list-ol",
ul: "editor-list-ul",
listitem: "editor-listitem",
},
image: "editor-image",
link: "editor-link",
text: {
bold: "editor-text-bold",
italic: "editor-text-italic",
},
};

export default exampleTheme;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { AutoLinkPlugin } from "@lexical/react/LexicalAutoLinkPlugin";

const URL_MATCHER =
/((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;

const EMAIL_MATCHER =
/(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;

const MATCHERS = [
(text: any) => {
const match = URL_MATCHER.exec(text);
return (
match && {
index: match.index,
length: match[0].length,
text: match[0],
url: match[0],
}
);
},
(text: any) => {
const match = EMAIL_MATCHER.exec(text);
return (
match && {
index: match.index,
length: match[0].length,
text: match[0],
url: `mailto:${match[0]}`,
}
);
},
];

export default function PlaygroundAutoLinkPlugin() {
return <AutoLinkPlugin matchers={MATCHERS} />;
}
Loading

0 comments on commit 2de3e7f

Please sign in to comment.