diff --git a/client/src/components/_test/test.component.jsx b/client/src/components/_test/test.component.jsx
index a14db2124..6a547176a 100644
--- a/client/src/components/_test/test.component.jsx
+++ b/client/src/components/_test/test.component.jsx
@@ -4,17 +4,21 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
import { selectBodyshop } from "../../redux/user/user.selectors";
+import { setEmailOptions } from "../../redux/email/email.actions";
+import { TemplateList } from "../../utils/TemplateConstants";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
-const mapDispatchToProps = (dispatch) => ({});
+const mapDispatchToProps = (dispatch) => ({
+ setEmailOptions: (e) => dispatch(setEmailOptions(e)),
+});
export default connect(
mapStateToProps,
mapDispatchToProps
-)(function Test({ bodyshop }) {
+)(function Test({ bodyshop, setEmailOptions }) {
const handle = async () => {
const response = await axios.post(
"/accounting/iif/receivables",
@@ -94,6 +98,24 @@ export default connect(
return (
+
diff --git a/client/src/components/email-overlay/email-overlay.component.jsx b/client/src/components/email-overlay/email-overlay.component.jsx
index 5481737df..b6961de1b 100644
--- a/client/src/components/email-overlay/email-overlay.component.jsx
+++ b/client/src/components/email-overlay/email-overlay.component.jsx
@@ -1,18 +1,26 @@
+import { UploadOutlined } from "@ant-design/icons";
import { Editor } from "@tinymce/tinymce-react";
-import { Input } from "antd";
+import { Button, Input, Upload, Select } from "antd";
import React from "react";
+
export default function EmailOverlayComponent({
messageOptions,
handleConfigChange,
+ handleToChange,
handleHtmlChange,
+ handleUpload,
+ handleFileRemove,
}) {
return (
To:
-
CC:
+
+
+
);
}
diff --git a/client/src/components/email-overlay/email-overlay.container.jsx b/client/src/components/email-overlay/email-overlay.container.jsx
index edbbddda2..46b82f493 100644
--- a/client/src/components/email-overlay/email-overlay.container.jsx
+++ b/client/src/components/email-overlay/email-overlay.container.jsx
@@ -4,17 +4,17 @@ import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
+import { logImEXEvent } from "../../firebase/firebase.utils";
import { toggleEmailOverlayVisible } from "../../redux/email/email.actions";
import {
selectEmailConfig,
selectEmailVisible,
} from "../../redux/email/email.selectors.js";
import { selectBodyshop } from "../../redux/user/user.selectors";
-import { EmailSettings } from "../../utils/TemplateConstants";
import RenderTemplate from "../../utils/RenderTemplate";
+import { EmailSettings } from "../../utils/TemplateConstants";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import EmailOverlayComponent from "./email-overlay.component";
-import { logImEXEvent } from "../../firebase/firebase.utils";
const mapStateToProps = createStructuredSelector({
modalVisible: selectEmailVisible,
@@ -33,6 +33,7 @@ export function EmailOverlayContainer({
bodyshop,
}) {
const { t } = useTranslation();
+
const [loading, setLoading] = useState(false);
const [sending, setSending] = useState(false);
const defaultEmailFrom = {
@@ -45,14 +46,27 @@ export function EmailOverlayContainer({
const [messageOptions, setMessageOptions] = useState({
...defaultEmailFrom,
html: "",
+ fileList: [],
});
const handleOk = async () => {
logImEXEvent("email_send_from_modal");
+ const attachments = [];
+
+ await asyncForEach(messageOptions.fileList, async (f) => {
+ const t = {
+ ContentType: f.type,
+ Filename: f.name,
+ Base64Content: (await toBase64(f)).split(",")[1],
+ };
+ attachments.push(t);
+ });
+ console.log("messageOptions", messageOptions);
+
setSending(true);
try {
- await axios.post("/sendemail", messageOptions);
+ await axios.post("/sendemail", { ...messageOptions, attachments });
notification["success"]({ message: t("emails.successes.sent") });
toggleEmailOverlayVisible();
} catch (error) {
@@ -71,17 +85,37 @@ export function EmailOverlayContainer({
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);
- console.log("emailConfig", emailConfig);
let html = await RenderTemplate(emailConfig.template, bodyshop);
setMessageOptions({
...emailConfig.messageOptions,
...defaultEmailFrom,
html: html,
+ fileList: [],
});
setLoading(false);
};
@@ -99,17 +133,22 @@ export function EmailOverlayContainer({
onCancel={() => {
toggleEmailOverlayVisible();
}}
- okButtonProps={{ loading: sending }}>
+ okButtonProps={{ loading: sending }}
+ >
@@ -120,3 +159,17 @@ export default connect(
mapStateToProps,
mapDispatchToProps
)(EmailOverlayContainer);
+
+const toBase64 = (file) =>
+ new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.readAsDataURL(file);
+ reader.onload = () => resolve(reader.result);
+ reader.onerror = (error) => reject(error);
+ });
+
+const asyncForEach = async (array, callback) => {
+ for (let index = 0; index < array.length; index++) {
+ await callback(array[index], index, array);
+ }
+};
diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.csi.component.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.csi.component.jsx
index 90215b219..5ba28dcae 100644
--- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.csi.component.jsx
+++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.csi.component.jsx
@@ -83,7 +83,7 @@ export function JobsDetailHeaderCsi({
if (e.key === "email")
setEmailOptions({
messageOptions: {
- to: job.ownr_ea,
+ to: [job.ownr_ea],
replyTo: bodyshop.email,
},
template: {
diff --git a/client/src/components/parts-order-modal/parts-order-modal.container.jsx b/client/src/components/parts-order-modal/parts-order-modal.container.jsx
index e364547c0..90fed10d4 100644
--- a/client/src/components/parts-order-modal/parts-order-modal.container.jsx
+++ b/client/src/components/parts-order-modal/parts-order-modal.container.jsx
@@ -148,7 +148,7 @@ export function PartsOrderModalContainer({
if (sendType === "e") {
setEmailOptions({
messageOptions: {
- to: data.vendors.filter((item) => item.id === values.id)[0] || null,
+ to: [data.vendors.filter((item) => item.id === values.id)[0]] || null,
replyTo: bodyshop.email,
},
template: {
@@ -216,17 +216,19 @@ export function PartsOrderModalContainer({
: t("parts_orders.labels.newpartsorder")
}
onCancel={() => toggleModalVisible()}
- width='90%'
+ width="90%"
onOk={() => form.submit()}
destroyOnClose
- forceRender>
- {error ?
: null}
+ forceRender
+ >
+ {error ?
: null}