Skip to content

Commit

Permalink
add example implementation of salutation placeholders in demo
Browse files Browse the repository at this point in the history
  • Loading branch information
juliawegmayr committed Dec 10, 2024
1 parent 7489620 commit af9c72f
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 7 deletions.
49 changes: 45 additions & 4 deletions demo/admin/src/common/blocks/RichTextBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,49 @@
import { CopyToClipboardButton } from "@comet/admin";
import { createRichTextBlock } from "@comet/cms-admin";
import { Box, FormLabel, List, ListItem, ListItemText, Paper } from "@mui/material";
import React from "react";
import { FormattedMessage } from "react-intl";

import { LinkBlock } from "./LinkBlock";

export const RichTextBlock = createRichTextBlock({
link: LinkBlock,
rte: { supports: ["bold", "italic", "header-one", "header-two", "header-three", "header-four", "header-five", "header-six"] },
});
const placeholders = [
{
placeholder: "{{SALUTATION}}",
helper: <FormattedMessage id="newsletter.richText.placeholder.salutation" defaultMessage="Dear Mr./Ms.LASTNAME" />,
},
];

export function createNewsletterRichTextBlock(): ReturnType<typeof createRichTextBlock> {
const RichTextBlock = createRichTextBlock({
link: LinkBlock,
rte: { supports: ["bold", "italic", "header-one", "header-two", "header-three", "header-four", "header-five", "header-six"] },
});

return {
...RichTextBlock,
AdminComponent: (rteAdminComponentProps) => (
<>
<Box mb={2}>
<RichTextBlock.AdminComponent {...rteAdminComponentProps} />
</Box>
<FormLabel>
<FormattedMessage id="newsletter.richText.placeholder.info" defaultMessage="Placeholders available in the text" />
</FormLabel>
<Paper variant="outlined">
<List>
{placeholders.map(({ placeholder, helper }) => {
const placeholderText = <Box sx={{ fontFamily: "monospace", fontWeight: "bold" }}>{placeholder}</Box>;
return (
<ListItem key={placeholder} secondaryAction={<CopyToClipboardButton copyText={placeholder} />}>
<ListItemText primary={placeholderText} secondary={helper} />
</ListItem>
);
})}
</List>
</Paper>
</>
),
};
}

export const RichTextBlock = createNewsletterRichTextBlock();
7 changes: 5 additions & 2 deletions demo/campaign/src/components/RenderedMail.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { renderToMjml } from "@luma-team/mjml-react";
import { EmailCampaignContentBlockData } from "@src/blocks.generated";
import { ContentBlock } from "@src/blocks/ContentBlock";
import { getPreparedHtml } from "@src/util/getPreparedHtml";
import { replaceMailHtmlPlaceholders } from "@src/util/replaceMailHtmlPlaceholders";
import * as React from "react";
import { IntlConfig, IntlProvider } from "react-intl";

Expand Down Expand Up @@ -34,9 +36,10 @@ export const RenderedMail: React.FC<Props> = ({ mjmlContent }) => {
React.useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mjml2htmlBrowser = require("mjml-browser");
const { html: mjmlHtml, errors } = mjml2htmlBrowser(mjmlContent);
const { html: escapedHtml, errors } = mjml2htmlBrowser(mjmlContent);

const html = mjmlHtml;
const preparedHtml = getPreparedHtml(escapedHtml);
const html = replaceMailHtmlPlaceholders(preparedHtml, "preview");

if (errors.length) {
// eslint-disable-next-line no-console
Expand Down
6 changes: 5 additions & 1 deletion demo/campaign/src/pages/api/index.page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { generateMjmlMailContent } from "@src/components/RenderedMail";
import { getMessages } from "@src/lang";
import { getPreparedHtml } from "@src/util/getPreparedHtml";
import { replaceMailHtmlPlaceholders } from "@src/util/replaceMailHtmlPlaceholders";
import mjml2html from "mjml";
import { NextApiRequest, NextApiResponse } from "next";
import { z } from "zod";
Expand All @@ -25,7 +27,9 @@ export default async function getMailHtml(request: NextApiRequest, response: Nex

const [messages] = await Promise.all([getMessages(scope.language)]);
const mjmlContent = generateMjmlMailContent(content, { locale: scope.language, messages, defaultLocale: scope.language });
const { html } = mjml2html(mjmlContent);
const { html: escapedHtml } = mjml2html(mjmlContent);
const preparedHtml = getPreparedHtml(escapedHtml);
const html = replaceMailHtmlPlaceholders(preparedHtml, "mail");

response.setHeader("Content-Type", "text/html; charset=utf-8");
response.write(html);
Expand Down
11 changes: 11 additions & 0 deletions demo/campaign/src/util/getPreparedHtml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const HIDE_IN_OUTLOOK_START_IF = "__IF_NOT_OUTLOOK__";
export const HIDE_IN_OUTLOOK_END_IF = "__END_IF__";

// Helper for hiding elements from Outlook/Windows Mail
// Replaces placeholder with conditional statement to tell the client to ignore the contained content if it's not Outlook/Windows Mail
// MJML escapes special characters, so this function replaces the placeholder after MJML generates html
export const getPreparedHtml = (html: string) => {
return html
.replace(new RegExp(HIDE_IN_OUTLOOK_START_IF, "g"), "<!--[if !mso]><!-- -->")
.replace(new RegExp(HIDE_IN_OUTLOOK_END_IF, "g"), "<!--<![endif]-->");
};
34 changes: 34 additions & 0 deletions demo/campaign/src/util/replaceMailHtmlPlaceholders.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
type Placeholder = {
preview: string;
mail: string;
};

const getPreviewHtml = (previewText: string) => {
return `<code style="background-color: rgba(41, 182, 246, 0.1); outline: 1px solid rgb(41, 182, 246)">${previewText}</code>`;
};

export const replaceMailHtmlPlaceholders = (html: string, type: "mail" | "preview") => {
let newHtml = html;
const placeholders: Record<string, Placeholder> = {
"{{SALUTATION}}": {
mail: [
'{% if ( contact.LASTNAME ) and (contact.SALUTATION == "MALE" ) %}',
`Dear Mr. {{contact.LASTNAME}} `,
'{% elif ( contact.LASTNAME ) and ( contact.SALUTATION == "FEMALE" ) %}',
`Dear Ms. {{contact.LASTNAME}}`,
"{% elif ( contact.LASTNAME )%}",
`Dear Mr./Ms. {{contact.LASTNAME}}`,
"{% else %}",
"Dear Ladies and Gentlemen",
"{% endif %}",
].join(""),

preview: getPreviewHtml("Dear Ladies and Gentlemen "),
},
};
for (const placeholder in placeholders) {
newHtml = newHtml.replace(new RegExp(placeholder, "g"), placeholders[placeholder][type]);
}

return newHtml;
};

0 comments on commit af9c72f

Please sign in to comment.