SendGrid Dynamic Templates + Firebase Functions (Node.js) not erroring, but not sending an email - node.js

I am trying to use the dynamic template feature with SendGrid with my Firebase Functions (Node.js), but my mail is not sending for some reason. I get a few errors thrown, but they shouldn't be preventing the email from sending.
When I save the SG template on the web app, I get a pop-up notification saying: Your template has been successfully saved, but we've detected an issue with your handlebars code that requires attention. I have messed around with fixing this and can't find anything to make the "handlebars issue" go away.
On the firebase functions console, I get the below logs:
Any ideas why I am not getting the email in my inbox? Everything was working fine when I was just passing an HTML snippet directly to the send() method.
Node.js snippet:
const heading = "New Website Contact Message!";
const body =
`
<div>
<h3>Message Details:</h3>
<p><b>Name</b>: ${newValues.name}</p>
<p><b>Email</b>: ${newValues.email}</p>
<p>
<b>Message</b>:
<br/>
${newValues.body}
</p>
<hr/>
<p>
You can reply directly to this email to continue the email thread with the user who sent the message.
</p>
</div>
`;
// Pack It
const msg = {
to: sensitiveSiteData.messengers,
from: `${publicSiteData.name} <${publicSiteData.emails.noreply}>`,
replyTo: `${newValues.email}`,
cc: "",
bcc: [],
// Create this template on SendGrid: https://mc.sendgrid.com/dynamic-templates
template_id: "d-3ce711231142141241241241241",
dynamic_template_data: {
"subject": "New " + publicSiteData.name + " Contact Message",
"siteName": publicSiteData.name,
"logoUrl": publicSiteData.logo.url,
"logoWidth": publicSiteData.logo.width,
"heading": heading,
"body": body,
"colors": publicSiteData.theme.schemes.light.colors,
"emails": publicSiteData.emails,
"ppUrl": publicSiteData.projectId + ".web.app/privacy-policy",
"termsUrl": publicSiteData.projectId + ".web.app/terms",
},
text: `${newValues.name} <${newValues.email}>: ${newValues.body}`,
};
// Send it
allPromises.push(
sgMail.send(msg).then(() => {
console.log("Email sent");
}).catch((error: any) => {
console.error(error);
})
);
SendGrid HTML template:
<html>
<head>
<title>{{{ insert heading 'default=Fire React Base Email' }}}</title>
</head>
<body>
<div style="width: 100%; font-family: Arial, Helvetica, sans-serif;">
<div style="text-align: center;">
<img
alt="{{{ insert siteName 'default=Fire React Base' }}} logo"
src="{{{ insert logoUrl 'default=https://firebasestorage.googleapis.com/v0/b/test-fire-react-base.appspot.com/o/public%2Flogos%2Flogo192.png?alt=media' }}}"
width="{{{ insert logoWidth 'default=150' }}}px"
height="auto"
/>
</div>
<h1 style="margin: 20px 0 0 0; text-align: center; color: {{{ insert colors.primary 'default=black' }}} !important;">
{{{ insert siteName 'default=Fire React Base' }}}
</h1>
<div style="margin: auto; width: 80%; padding: 1%;">
<h2>{{{ insert heading 'default=Heading Here' }}}</h2>
<div style="border: solid {{{ insert colors.primary 'default=black' }}} 2px; padding: 5%;">
{{{
insert body
'
default=Tempor officia officia commodo labore do ut qui laboris occaecat nulla esse excepteur. Officia est exercitation ex laborum qui. Nostrud magna excepteur qui incididunt velit eiusmod consequat laborum ea laborum aliquip ut. Id ut fugiat elit adipisicing cillum nulla veniam anim nisi ea velit. Mollit dolore proident minim reprehenderit officia fugiat. Ea ea occaecat dolor est ipsum cupidatat tempor eu dolor amet. In deserunt elit in commodo tempor consectetur id excepteur mollit ea aliquip. Adipisicing incididunt commodo officia amet velit ea deserunt deserunt enim ipsum reprehenderit Lorem elit. Lorem ex pariatur elit ut anim excepteur nostrud nostrud dolore nulla. Ad ex mollit proident enim quis eu ipsum cupidatat irure non quis. Labore veniam consequat pariatur sunt eu quis qui occaecat aute sunt et dolor est ullamco. Sunt Lorem adipisicing id elit.
'
}}}
</div>
<div style="text-align: center; margin: 25px 0; font-size: 14px;">
<p>
Questions? Contact
{{{ insert emails.support 'default=help#company.com' }}}
</p>
<p>
Privacy Policy
Terms & Conditions
</p>
<p>Powered by Company</p>
</div>
</div>
</div>
</body>
</html>

Related

How do I create a sticky (non scrollable) header/footer in a FluentUI modal control?

Using a React Fluent UI Modal Control, could someone please show me how to:
Ensure the header and footer are not part of the scrollable content (i.e. they are 'sticky', while the main content sitting between them is scrollable if the window size is insufficient).
Minimise the change in modal size as content changes - that is the window sizes to the viewport as initially, but as the content changes dynamically, the modal maintains it original size.
Below is an edited example from the relevant Microsoft documentation. I have also put it in this codepen which works (unlike the snippet). Clicking the button in the footer of the modal control alters the amount of content.
const { useBoolean } = window.FluentUIReactHooks;
const { getTheme, mergeStyleSets, FontWeights, ContextualMenu, Toggle, Modal, IDragOptions, IIconProps, Stack, IStackProps, DefaultButton, IconButton, IButtonStyles, ThemeProvider, initializeIcons, Separator, PrimaryButton } = window.FluentUIReact;
// Initialize icons in case this example uses them
initializeIcons();
const ModalBasicExample: React.FunctionComponent = () => {
const [isModalOpen, { setTrue: showModal, setFalse: hideModal }] = useBoolean(false);
const [pageNo, setPageNo] = React.useState(0);
const changePage = React.useCallback(() => setPageNo(oldVal => ~oldVal),[setPageNo])
const titleId = "titleId";
return (
<div>
<DefaultButton onClick={showModal} text="Open Modal" />
<Modal
titleAriaId={titleId}
isOpen={isModalOpen}
onDismiss={hideModal}
isBlocking={false}
containerClassName={contentStyles.container}
topOffsetFixed={true}
>
<div className={contentStyles.header}>
<span id={titleId}>Lorem Ipsum</span>
<IconButton
styles={iconButtonStyles}
iconProps={cancelIcon}
ariaLabel="Close popup modal"
onClick={hideModal}
/>
</div>
<div className={contentStyles.body}>
{pageNo===0 ? <div dangerouslySetInnerHTML={{
__html:lorem}}></div> : <p>page {pageNo}</p>}
</div>
<footer className={contentStyles.footer}>
<Separator/>
<PrimaryButton text="switch" onClick={changePage}/>
</footer>
</Modal>
</div>
);
};
const cancelIcon: IIconProps = { iconName: 'Cancel' };
const theme = getTheme();
const contentStyles = mergeStyleSets({
container: {
display: 'flex',
flexFlow: 'column nowrap',
alignItems: 'stretch',
},
header: [
// eslint-disable-next-line deprecation/deprecation
theme.fonts.xLargePlus,
{
flex: '1 1 auto',
borderTop: `4px solid ${theme.palette.themePrimary}`,
color: theme.palette.neutralPrimary,
display: 'flex',
alignItems: 'center',
fontWeight: FontWeights.semibold,
padding: '12px 12px 14px 24px',
},
],
body: {
flex: '4 4 auto',
padding: '0 24px 24px 24px',
overflowY: 'hidden',
selectors: {
p: { margin: '14px 0' },
'p:first-child': { marginTop: 0 },
'p:last-child': { marginBottom: 0 },
},
},
footer: {
}
});
const iconButtonStyles: Partial<IButtonStyles> = {
root: {
color: theme.palette.neutralPrimary,
marginLeft: 'auto',
marginTop: '4px',
marginRight: '2px',
},
rootHovered: {
color: theme.palette.neutralDark,
},
};
const lorem = "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc suscipit, est eget porta tempor, ante justo finibus odio, sit amet rhoncus neque velit nec leo. Morbi vitae ex a urna auctor sagittis dictum at ante. Etiam vel commodo turpis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean dapibus malesuada luctus. Vivamus nec convallis dolor, nec condimentum ligula. Aenean blandit mi et justo rutrum, sed feugiat erat gravida. Donec sit amet eleifend mauris. Duis eget leo vel elit viverra ullamcorper. Quisque eu purus nec diam convallis suscipit.</p>".repeat(7);
const ModalBasicExampleWrapper = () => <ThemeProvider><ModalBasicExample /></ThemeProvider>;
ReactDOM.render(<ModalBasicExampleWrapper />, document.getElementById('content'))
<script src="https://unpkg.com/#fluentui/react#8/dist/fluentui-react.js"></script>
<script src="https://unpkg.com/#fluentui/react-hooks#8/dist/react-hooks.js"></script>
<div id="content"></div>

Align sup tag within centered flexbox

I'm struggeling to align the sup tag in the right position within a centered flexbox
.card {
display: flex;
align-items: center;
padding: 2rem 1rem;
border: 1px solid blue;
sup {
color: red;
}
}
<div class="container">
<div class="card">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium, nam reprehenderit eum assumenda illo voluptatibus fugit reiciendis impedit omnis provident dolorum quae itaque quaerat perferendis est? Exercitationem, quas. Blanditiis, dignissimos. Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium, nam reprehenderit eum assumenda illo voluptatibus fugit reiciendis impedit omnis provident dolorum quae itaque quaerat perferendis est? Exercitationem, quas. Blanditiis, dignissimos.<sup>3</sup>
</div>
</div>
Here is my code on codepen:
https://codepen.io/Bizboss/pen/eYBNGVR
<sup>need to be in a <p> tag
.card {
display: flex;
align-items: center;
padding: 2rem 1rem;
border: 1px solid blue;
}
sup {
color: red;
}
<div class="container">
<div class="card">
<p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium, nam reprehenderit eum assumenda illo voluptatibus fugit reiciendis impedit omnis provident dolorum quae itaque quaerat perferendis est? Exercitationem, quas. Blanditiis, dignissimos. Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium, nam reprehenderit eum assumenda illo voluptatibus fugit reiciendis impedit omnis provident dolorum quae itaque quaerat perferendis est? Exercitationem, quas. Blanditiis, dignissimos.<sup>3</sup></p>
</div>
</div>

How to render line breaks contained in a string?

Line breaks contained in my strings merely render as <br> instead of actual line breaks.
I tried to use back-ticks to no avail. Is there a simple way to have line breaks rendered on the page, ideally without modify my code too deeply?
Markup:
<div
v-for="item in faqItems"
:key="item.id"
>
<span class="faq-item-title">
{{ item.title }}
</span>
<span class="faq-item-details">
{{ item.text }}
</span>
<svg-icon name="chevron-down"></svg-icon>
</div>
JS:
faqItems: [
{
title: 'Nullam vehicula arcu ipsum',
text: 'Donec sit amet nisl finibus, pharetra orci ut, aliquet diam.<br><br>Nunc cursus libero luctus nunc vestibulum placerat. Mauris vel dolor sit amet orci rutrum sollicitudin.<br><br>Donec neque leo, porttitor a diam et, sodales volutpat libero.'
},
{
title: 'In iaculis egestas nisl',
text: 'Etiam a elementum diam. Praesent lobortis pulvinar lacus, sit amet vehicula tortor.'
}
One way is to replace your <br>s with text line breaks (\n) and keep using it as text in layout:
{
title: 'Nullam vehicula arcu ipsum',
text: 'Donec sit amet nisl finibus, pharetra orci ut, aliquet diam.\n\nNunc cursus libero luctus nunc vestibulum placerat. Mauris vel dolor sit amet orci rutrum sollicitudin.\n\nDonec neque leo, porttitor a diam et, sodales volutpat libero.'
}
As Daniel pointed out, literal line breaks don't work in <span>. Unless you map it to .innerText property of the <span> => Example - which, under the hood, transforms all literal breaks into <br>s and divides the text into different text nodes, accordingly).
The other way is to use the dedicated Vue directive for this purpose, which parses the string as html: v-html.
<span class="faq-item-details" v-html="item.text" />
Use backticks and then add css entries as follows:
<div
v-for="item in faqItems"
:key="item.id"
>
<span class="faq-item-title" style="white-space: pre-wrap;">
{{ item.title }}
</span>
<span class="faq-item-details" style="white-space: pre-wrap;">
{{ item.text }}
</span>
<svg-icon name="chevron-down"></svg-icon>
</div>

Text gets below footer when zooming

Im experimenting a little with responsive design and i noticed that if you zoom the page in the browser or with smaller screens the text extends behind and below the footer despite it being set absolute with bottom: 0;
Can anyone explain how to solve this?
body {
margin: 0;
}
footer {
width: 590px;
height: 100px;
border: 5px solid black;
position: absolute;
bottom: 0;
}
footer h1 {
height:0px;
margin-left: 25px;
}
h1 {
font-size: 50px;
}
p {
text-align: justify;
}
.container {
width: 600px;
padding: 30px;
}
<!DOCTYPE=html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="test.css"/>
</head>
<body>
<div class="container">
<h1>heading</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<footer>
<h1>footer</h1>
</footer>
</div>
</body>
</html>

CSS MultiLined Gradient Text. -webkit-background-clip

I am using CSS to generate a gradient on my text... The problem is my text is multi-lined so the gradient doesn't reset on each line... the whole paragraph becomes 1 huge gradient! Can I get an individual gradient effect for each line of text in my divider? Here is my code:
<html>
<head>
<style type='text/css'>p.p1 {
margin: 0.0px 0.0px 0.0px 50.0px;
font: 50.0px Helvitica;
font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', 'Helvetica, Arial', 'Lucida Grande', 'sans-serif';
background: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#333));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body bgcolor='#FFFFFF'>
<div style='word-wrap: break-word;'>
<p class='p1'>
<font face='helvetica' color='#000000'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi id vestibulum lectus. Maecenas facilisis orci vitae urna pulvinar cursus. Etiam id laoreet metus. Cras vitae elit ipsum. Donec a sagittis nisi. Sed nec nisi nibh, fringilla fermentum quam. Vestibulum lorem felis, gravida et faucibus ac, ultrices nec lectus.
</font>
</p>
</div>
</body>
</html>
I got rid of the deprecated tags and cleaned the code up for you..
p.p1 {
margin: 0 0 0 50px;
font-size: 50px;
font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', 'Helvetica, Arial', 'Lucida Grande', 'sans-serif';
background: -webkit-repeating-linear-gradient(top, red 0px, blue 60px);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
Demo

Resources