Email Improvements.

This commit is contained in:
Patrick Fic
2021-04-08 13:55:24 -07:00
parent 54e5129fd4
commit 7f30439868
8 changed files with 179 additions and 119 deletions

View File

@@ -10669,6 +10669,74 @@
</concept_node>
</children>
</folder_node>
<folder_node>
<name>fields</name>
<children>
<concept_node>
<name>cc</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>subject</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>to</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>labels</name>
<children>

View File

@@ -1,68 +1,82 @@
import { UploadOutlined } from "@ant-design/icons";
import { Button, Card, Divider, Input, Select, Upload } from "antd";
import { Card, Divider, Form, Input, Select, Upload } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
export default function EmailOverlayComponent({
messageOptions,
handleConfigChange,
handleToChange,
handleHtmlChange,
handleUpload,
handleFileRemove,
}) {
export default function EmailOverlayComponent({ form }) {
const { t } = useTranslation();
return (
<div>
To:
<Select
<Form.Item
label={t("emails.fields.to")}
name="to"
mode="tags"
value={messageOptions.to}
//style={{ width: "100%" }}
onChange={handleToChange}
tokenSeparators={[",", ";"]}
/>
CC:
<Select
value={messageOptions.cc}
mode="tags"
onChange={(value) => handleConfigChange("cc", value)}
name="cc"
tokenSeparators={[",", ";"]}
/>
Subject:
<Input
value={messageOptions.subject}
onChange={(e) => handleConfigChange("subject", e.target.value)}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<Select mode="tags" tokenSeparators={[",", ";"]} />
</Form.Item>
<Form.Item label={t("emails.fields.cc")} name="cc">
<Select mode="tags" tokenSeparators={[",", ";"]} />
</Form.Item>
<Form.Item
label={t("emails.fields.subject")}
name="subject"
/>
<Divider>{t("emails.labels.preview")}</Divider>
<div
style={{
padding: "1rem",
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<Input />
</Form.Item>
backgroundColor: "lightgray",
borderLeft: "6px solid #2196F3",
<Divider>{t("emails.labels.preview")}</Divider>
<Form.Item shouldUpdate>
{() => {
return (
<div
style={{
padding: "1rem",
backgroundColor: "lightgray",
borderLeft: "6px solid #2196F3",
}}
dangerouslySetInnerHTML={{ __html: form.getFieldValue("html") }}
/>
);
}}
dangerouslySetInnerHTML={{ __html: messageOptions.html }}
/>
<Divider>
<Divider>{t("emails.labels.preview")}</Divider>
</Divider>
</Form.Item>
<Card title={t("emails.labels.attachments")}>
<Upload
fileList={messageOptions.fileList}
beforeUpload={handleUpload}
onRemove={handleFileRemove}
multiple
listType="picture-card"
style={{ width: "100%" }}
<Form.Item
name="fileList"
valuePropName="fileList"
getValueFromEvent={(e) => {
console.log("Upload event:", e);
if (Array.isArray(e)) {
return e;
}
return e && e.fileList;
}}
>
<Button>
<UploadOutlined /> Upload
</Button>
</Upload>
<Upload.Dragger multiple listType="picture-card">
<>
<p className="ant-upload-drag-icon">
<UploadOutlined />
</p>
<p className="ant-upload-text">
Click or drag files to this area to upload.
</p>
</>
</Upload.Dragger>
</Form.Item>
</Card>
</div>
);

View File

@@ -1,4 +1,4 @@
import { Modal, notification } from "antd";
import { Form, Modal, notification } from "antd";
import axios from "axios";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
@@ -10,7 +10,10 @@ import {
selectEmailConfig,
selectEmailVisible,
} from "../../redux/email/email.selectors.js";
import { selectBodyshop } from "../../redux/user/user.selectors";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import RenderTemplate from "../../utils/RenderTemplate";
import { EmailSettings } from "../../utils/TemplateConstants";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
@@ -20,6 +23,7 @@ const mapStateToProps = createStructuredSelector({
modalVisible: selectEmailVisible,
emailConfig: selectEmailConfig,
bodyshop: selectBodyshop,
currentUser: selectCurrentUser,
});
const mapDispatchToProps = (dispatch) => ({
@@ -31,31 +35,27 @@ export function EmailOverlayContainer({
modalVisible,
toggleEmailOverlayVisible,
bodyshop,
currentUser,
}) {
const { t } = useTranslation();
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [sending, setSending] = useState(false);
const [rawHtml, setRawHtml] = useState("");
const defaultEmailFrom = {
from: {
name: bodyshop.shopname || EmailSettings.fromNameDefault,
name: `${currentUser.displayName} @ ${bodyshop.shopname}`,
address: EmailSettings.fromAddress,
},
replyTo: bodyshop.email,
ReplyTo: { Email: currentUser.email, Name: currentUser.displayName },
};
const [messageOptions, setMessageOptions] = useState({
...defaultEmailFrom,
html: "",
fileList: [],
});
const handleOk = async () => {
const handleFinish = async (values) => {
logImEXEvent("email_send_from_modal");
console.log(`values`, values);
const attachments = [];
await asyncForEach(messageOptions.fileList, async (f) => {
await asyncForEach(values.fileList, async (f) => {
const t = {
ContentType: f.type,
Filename: f.name,
@@ -67,7 +67,8 @@ export function EmailOverlayContainer({
setSending(true);
try {
await axios.post("/sendemail", {
...messageOptions,
...defaultEmailFrom,
...values,
html: rawHtml,
attachments,
});
@@ -82,34 +83,6 @@ export function EmailOverlayContainer({
setSending(false);
};
const handleConfigChange = (name, value) => {
setMessageOptions({ ...messageOptions, [name]: value });
};
const handleHtmlChange = (text) => {
setMessageOptions({ ...messageOptions, html: text });
};
const handleToChange = (recipients) => {
setMessageOptions({ ...messageOptions, to: recipients });
};
const handleUpload = (file) => {
setMessageOptions({
...messageOptions,
fileList: [...messageOptions.fileList, file],
});
return false;
};
const handleFileRemove = (file) => {
setMessageOptions((state) => {
const index = state.fileList.indexOf(file);
const newfileList = state.fileList.slice();
newfileList.splice(index, 1);
return {
fileList: newfileList,
};
});
};
const render = async () => {
logImEXEvent("email_render_template", { template: emailConfig.template });
setLoading(true);
@@ -120,11 +93,9 @@ export function EmailOverlayContainer({
url: `${window.location.protocol}://${window.location.host}/`,
});
setRawHtml(response.data);
console.log("response", response);
setMessageOptions({
form.setFieldsValue({
...emailConfig.messageOptions,
...defaultEmailFrom,
html: response.data,
fileList: [],
});
@@ -140,29 +111,16 @@ export function EmailOverlayContainer({
destroyOnClose={true}
visible={modalVisible}
width={"80%"}
onOk={handleOk}
onOk={() => form.submit()}
onCancel={() => {
toggleEmailOverlayVisible();
}}
okButtonProps={{ loading: sending }}
>
<LoadingSpinner loading={loading}>
<EmailOverlayComponent
handleConfigChange={handleConfigChange}
messageOptions={messageOptions}
handleHtmlChange={handleHtmlChange}
handleUpload={handleUpload}
handleFileRemove={handleFileRemove}
handleToChange={handleToChange}
/>
<button
onClick={() => {
navigator.clipboard.writeText(messageOptions.html);
}}
>
Copy HTML
</button>
</LoadingSpinner>
<Form layout="vertical" form={form} onFinish={handleFinish}>
{loading && <LoadingSpinner />}
<EmailOverlayComponent form={form} />
</Form>
</Modal>
);
}

View File

@@ -686,6 +686,11 @@
"errors": {
"notsent": "Email not sent. Error encountered while sending {{message}}"
},
"fields": {
"cc": "CC",
"subject": "Subject",
"to": "To"
},
"labels": {
"attachments": "Attachments",
"preview": "Email Preview"

View File

@@ -686,6 +686,11 @@
"errors": {
"notsent": "Correo electrónico no enviado Se encontró un error al enviar {{message}}"
},
"fields": {
"cc": "",
"subject": "",
"to": ""
},
"labels": {
"attachments": "",
"preview": ""

View File

@@ -686,6 +686,11 @@
"errors": {
"notsent": "Courriel non envoyé. Erreur rencontrée lors de l'envoi de {{message}}"
},
"fields": {
"cc": "",
"subject": "",
"to": ""
},
"labels": {
"attachments": "",
"preview": ""

View File

@@ -136,7 +136,12 @@ export const GenerateDocument = async (template, messageOptions, sendType) => {
if (sendType === "e") {
store.dispatch(
setEmailOptions({
messageOptions,
messageOptions: {
...messageOptions,
to: Array.isArray(messageOptions.to)
? messageOptions.to
: [messageOptions.to],
},
template,
})
);

View File

@@ -42,8 +42,8 @@ exports.sendEmail = async (req, res) => {
return { Email: i };
}),
ReplyTo: {
Email: req.body.from.address,
Name: req.body.from.name,
Email: req.body.ReplyTo.Email,
Name: req.body.ReplyTo.Name,
},
Subject: req.body.subject,
// TextPart: