diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 7470ea1e8..736b186b1 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -11390,7 +11390,133 @@ jobs - repairorder + appointment_reminder + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + casl_work_authorization + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + coversheet + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + estimate_detail + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + fippa_work_authorization + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + job_totals + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + work_authorization false @@ -11415,6 +11541,48 @@ labels + + misc + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + repairorder + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + title false diff --git a/client/src/components/email-overlay/email-overlay.container.jsx b/client/src/components/email-overlay/email-overlay.container.jsx index df660895e..4016ca301 100644 --- a/client/src/components/email-overlay/email-overlay.container.jsx +++ b/client/src/components/email-overlay/email-overlay.container.jsx @@ -1,21 +1,20 @@ import { useApolloClient } from "@apollo/react-hooks"; import { Modal, notification } from "antd"; -import { gql } from "apollo-boost"; import axios from "axios"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import { QUERY_TEMPLATES_BY_NAME } from "../../graphql/templates.queries"; +import { EmailSettings } from "../../emails/constants"; import { toggleEmailOverlayVisible } from "../../redux/email/email.actions"; import { selectEmailConfig, selectEmailVisible, } from "../../redux/email/email.selectors.js"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import RenderTemplate from "../../utils/RenderTemplate"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import EmailOverlayComponent from "./email-overlay.component"; -import { EmailSettings } from "../../emails/constants"; const mapStateToProps = createStructuredSelector({ modalVisible: selectEmailVisible, @@ -32,6 +31,7 @@ export function EmailOverlayContainer({ bodyshop, }) { const { t } = useTranslation(); + const [loading, setLoading] = useState(false); const defaultEmailFrom = { from: { name: bodyshop.shopname || EmailSettings.fromNameDefault, @@ -41,58 +41,10 @@ export function EmailOverlayContainer({ }; const [messageOptions, setMessageOptions] = useState({ ...defaultEmailFrom, + html: "", }); const client = useApolloClient(); - const renderEmail = () => { - client - .query({ - query: QUERY_TEMPLATES_BY_NAME, - variables: { name: emailConfig.template.name }, - fetchPolicy: "network-only", - }) - .then(({ data: templateRecords }) => { - let templateToUse; - if (templateRecords.templates.length === 1) { - console.log("Only 1 Template found."); - templateToUse = templateRecords.templates[0]; - } else if (templateRecords.templates.length === 2) { - console.log("2 Templates found.."); - templateToUse = templateRecords.templates.filter( - (t) => !!t.bodyshopid - ); - } else { - //No template found.Uh oh. - alert("Templating Error!"); - } - - client - .query({ - query: gql(templateToUse.query), - variables: { ...emailConfig.template.variables }, - fetchPolicy: "network-only", - }) - .then(({ data: contextData }) => { - handleRender(contextData, templateToUse.html); - }); - }); - }; - - const handleRender = (contextData, html) => { - axios - .post("/render", { - view: html, - context: { ...contextData, bodyshop: bodyshop }, - }) - .then((r) => { - setMessageOptions({ - ...emailConfig.messageOptions, - ...defaultEmailFrom, - html: r.data, - }); - }); - }; - const handleOk = () => { //sendEmail(messageOptions); axios @@ -118,8 +70,19 @@ export function EmailOverlayContainer({ setMessageOptions({ ...messageOptions, html: text }); }; + const render = async () => { + setLoading(true); + let html = await RenderTemplate(emailConfig.template, client, bodyshop); + setMessageOptions({ + ...emailConfig.messageOptions, + ...defaultEmailFrom, + html: html, + }); + setLoading(false); + }; + useEffect(() => { - if (modalVisible) renderEmail(); + if (modalVisible) render(); }, [modalVisible]); // eslint-disable-line react-hooks/exhaustive-deps return ( @@ -131,7 +94,7 @@ export function EmailOverlayContainer({ onCancel={() => { toggleEmailOverlayVisible(); }}> - + ({ setEmailOptions: (e) => dispatch(setEmailOptions(e)), @@ -15,8 +19,46 @@ export function PrintCenterItemComponent({ printCenterModal, setEmailOptions, item, + id, + bodyshop, + disabled, }) { - return
  • {item.title}
  • ; + const client = useApolloClient(); + + const renderToNewWindow = async () => { + const html = await RenderTemplate( + { + name: item.key, + variables: { id: id }, + }, + client, + bodyshop + ); + + var newWin = window.open(); + newWin.document.write(html); + }; + + if (disabled) return
  • {item.title}
  • ; + return ( +
  • + {item.title} + + { + setEmailOptions({ + messageOptions: { + Subject: "TODO FIX ME", + }, + template: { + name: item.key, + variables: { id: id }, + }, + }); + }} + /> +
  • + ); } export default connect( mapStateToProps, diff --git a/client/src/components/print-center-jobs/print-center-jobs.component.jsx b/client/src/components/print-center-jobs/print-center-jobs.component.jsx index cea8a3917..de938e66c 100644 --- a/client/src/components/print-center-jobs/print-center-jobs.component.jsx +++ b/client/src/components/print-center-jobs/print-center-jobs.component.jsx @@ -1,6 +1,5 @@ import { Collapse } from "antd"; import React from "react"; -import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { setEmailOptions } from "../../redux/email/email.actions"; @@ -10,8 +9,8 @@ import { selectBodyshop, selectCurrentUser, } from "../../redux/user/user.selectors"; -import JobsReports from "./print-center-jobs.list"; import PrintCenterItem from "../print-center-item/print-center-item.component"; +import JobsReports from "./print-center-jobs.list"; const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, @@ -23,20 +22,23 @@ const mapDispatchToProps = (dispatch) => ({ toggleModalVisible: () => dispatch(toggleModalVisible("printCenter")), }); export function PrintCenterJobsComponent({ printCenterModal }) { - const { t } = useTranslation(); - const { id: jobid } = printCenterModal.context; + const { id: jobId } = printCenterModal.context; const JobsReportsList = JobsReports(null); return (
    - Print Center Jobs COmponetn {JobsReportsList.map((section) => (
      {section.items.map((item) => ( - + ))}
    diff --git a/client/src/components/print-center-jobs/print-center-jobs.list.js b/client/src/components/print-center-jobs/print-center-jobs.list.js index e97f6df58..afbb0d0f4 100644 --- a/client/src/components/print-center-jobs/print-center-jobs.list.js +++ b/client/src/components/print-center-jobs/print-center-jobs.list.js @@ -3,46 +3,56 @@ import i18n from "i18next"; export default function JobsReports(job) { return [ { - title: i18n.t("printcenter.jobs.repairorder"), + title: i18n.t("printcenter.labels.repairorder"), key: "printcenter.jobs.repairorder", disabled: false, items: [ { key: "appointment_reminder", - title: "Appointment Reminder", + title: i18n.t("printcenter.jobs.appointment_reminder"), disabled: false, }, { - key: "appointment_reminder2", - title: "Appointment Reminder2", + key: "estimate_detail", + title: i18n.t("printcenter.jobs.estimate_detail"), disabled: false, }, { - key: "appointment_reminder3", - title: "Appointment Reminder3", + key: "job_totals", + title: i18n.t("printcenter.jobs.job_totals"), disabled: false, }, { - key: "appointment_reminder4", - title: "Appointment Reminder4", + key: "work_authorization", + title: i18n.t("printcenter.jobs.work_authorization"), disabled: false, }, { - key: "appointment_reminder5", - title: "Appointment Reminder5", + key: "fippa_work_authorization", + title: i18n.t("printcenter.jobs.fippa_work_authorization"), + disabled: false, + }, + { + key: "casl_work_authorization", + title: i18n.t("printcenter.jobs.casl_work_authorization"), + disabled: false, + }, + { + key: "coversheet", + title: i18n.t("printcenter.jobs.coversheet"), disabled: false, }, ], }, { - title: "Section 2", - key: "Section2", + title: i18n.t("printcenter.labels.misc"), + key: "printcenter.jobs.misc", disabled: false, items: [ { - key: "appointment_reminder12", - title: "Appointment Reminder12", - disabled: false, + key: "iou", + title: i18n.t("printcenter.jobs.iou"), + disabled: true, }, ], }, diff --git a/client/src/components/print-center-modal/print-center-modal.container.jsx b/client/src/components/print-center-modal/print-center-modal.container.jsx index 66736d3fc..0d53b1e65 100644 --- a/client/src/components/print-center-modal/print-center-modal.container.jsx +++ b/client/src/components/print-center-modal/print-center-modal.container.jsx @@ -11,6 +11,7 @@ import { selectCurrentUser, } from "../../redux/user/user.selectors"; import PrintCenterModalComponent from "./print-center-modal.component"; +import "./print-center-modal.styles.scss"; const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, diff --git a/client/src/components/print-center-modal/print-center-modal.styles.scss b/client/src/components/print-center-modal/print-center-modal.styles.scss new file mode 100644 index 000000000..0303e1da3 --- /dev/null +++ b/client/src/components/print-center-modal/print-center-modal.styles.scss @@ -0,0 +1,3 @@ +.print-center-item > * { + padding: 0em 8px; +} diff --git a/client/src/redux/application/application.actions.js b/client/src/redux/application/application.actions.js index a3649f769..bafacf052 100644 --- a/client/src/redux/application/application.actions.js +++ b/client/src/redux/application/application.actions.js @@ -12,4 +12,4 @@ export const endLoading = (options) => ({ export const setBreadcrumbs = (breadcrumbs) => ({ type: ApplicationActionTypes.SET_BREAD_CRUMBS, payload: breadcrumbs, -}); +}); \ No newline at end of file diff --git a/client/src/redux/application/application.sagas.js b/client/src/redux/application/application.sagas.js index ec20c8a97..9deb690b2 100644 --- a/client/src/redux/application/application.sagas.js +++ b/client/src/redux/application/application.sagas.js @@ -1,7 +1,4 @@ -import { all, call, put, takeLatest } from "redux-saga/effects"; -// import { sendEmailFailure, sendEmailSuccess } from "./email.actions"; -// import EmailActionTypes from "./email.types"; -import axios from "axios"; +import { all } from "redux-saga/effects"; // export function* onSendEmail() { // yield takeLatest(EmailActionTypes.SEND_EMAIL, sendEmail); @@ -31,12 +28,12 @@ import axios from "axios"; // } // } -// export function* onSendEmailFailure() { -// yield takeLatest(EmailActionTypes.SEND_EMAIL_FAILURE, sendEmailFailureSaga); +// export function* onRenderTemplate() { +// yield takeLatest(ApplicationActionTypes.RENDER_TEMPLATE, renderTemplate); // } -// export function* sendEmailFailureSaga(error) { +// export function* renderTemplate({ payload: template }) { // try { -// yield console.log(error); +// yield console.log("Render Template Saga => template", template); // } catch (error) { // console.log("Error in sendEmailFailure saga.", error.message); // } @@ -47,5 +44,6 @@ export function* applicationSagas() { // call(onSendEmail), // call(onSendEmailFailure), // call(onSendEmailSuccess) + //call(onRenderTemplate), ]); } diff --git a/client/src/redux/email/email.sagas.js b/client/src/redux/email/email.sagas.js index a7b562d48..a9b1a250a 100644 --- a/client/src/redux/email/email.sagas.js +++ b/client/src/redux/email/email.sagas.js @@ -1,51 +1,66 @@ -import { all, call, put, takeLatest } from "redux-saga/effects"; -import { sendEmailFailure, sendEmailSuccess } from "./email.actions"; -import EmailActionTypes from "./email.types"; -import axios from "axios"; +import { all } from "redux-saga/effects"; +// import { sendEmailFailure, sendEmailSuccess } from "./email.actions"; +// import { renderTemplate } from "../application/application.actions"; +// import EmailActionTypes from "./email.types"; +// import axios from "axios"; -export function* onSendEmail() { - yield takeLatest(EmailActionTypes.SEND_EMAIL, sendEmail); -} -export function* sendEmail(payload) { - try { - console.log("Sending thta email", payload); - axios.post("/sendemail", payload).then(response => { - console.log(JSON.stringify(response)); - put(sendEmailSuccess()); - }); - } catch (error) { - console.log("Error in sendEmail saga."); - yield put(sendEmailFailure(error.message)); - } -} +// export function* onSendEmail() { +// yield takeLatest(EmailActionTypes.SEND_EMAIL, sendEmail); +// } +// export function* sendEmail(payload) { +// try { +// console.log("Sending thta email", payload); +// axios.post("/sendemail", payload).then(response => { +// console.log(JSON.stringify(response)); +// put(sendEmailSuccess()); +// }); +// } catch (error) { +// console.log("Error in sendEmail saga."); +// yield put(sendEmailFailure(error.message)); +// } +// } -export function* onSendEmailSuccess() { - yield takeLatest(EmailActionTypes.SEND_EMAIL_SUCCESS, sendEmailSuccessSaga); -} -export function* sendEmailSuccessSaga() { - try { - console.log("Send email success."); - } catch (error) { - console.log("Error in sendEmailSuccess saga."); - yield put(sendEmailFailure(error.message)); - } -} +// export function* onSendEmailSuccess() { +// yield takeLatest(EmailActionTypes.SEND_EMAIL_SUCCESS, sendEmailSuccessSaga); +// } +// export function* sendEmailSuccessSaga() { +// try { +// console.log("Send email success."); +// } catch (error) { +// console.log("Error in sendEmailSuccess saga."); +// yield put(sendEmailFailure(error.message)); +// } +// } -export function* onSendEmailFailure() { - yield takeLatest(EmailActionTypes.SEND_EMAIL_FAILURE, sendEmailFailureSaga); -} -export function* sendEmailFailureSaga(error) { - try { - yield console.log(error); - } catch (error) { - console.log("Error in sendEmailFailure saga.", error.message); - } -} +// export function* onSendEmailFailure() { +// yield takeLatest(EmailActionTypes.SEND_EMAIL_FAILURE, sendEmailFailureSaga); +// } +// export function* sendEmailFailureSaga(error) { +// try { +// yield console.log(error); +// } catch (error) { +// console.log("Error in sendEmailFailure saga.", error.message); +// } +//} + +// export function* onSetEmailOptions() { +// yield takeLatest(EmailActionTypes.SET_EMAIL_OPTIONS, setEmailOptions); +// } +// export function* setEmailOptions({ payload: { template } }) { +// console.log("function*setEmailOptions -> template", template); + +// try { +// yield put(renderTemplate(template)); +// } catch (error) { +// console.log("Error in setEmailOptions saga.", error.message); +// } +// } export function* emailSagas() { yield all([ - call(onSendEmail), - call(onSendEmailFailure), - call(onSendEmailSuccess) + // call(onSendEmail), + // call(onSendEmailFailure), + // call(onSendEmailSuccess) + //call(onSetEmailOptions), ]); } diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index fc7789eb0..f04c2e04d 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -737,9 +737,17 @@ "nocontexttype": "No context type set." }, "jobs": { - "repairorder": "Repair Order Related" + "appointment_reminder": "Appointment Reminder", + "casl_work_authorization": "CASL Work Authorization", + "coversheet": "Coversheet", + "estimate_detail": "Estimate Details", + "fippa_work_authorization": "FIPPA Work Authorization", + "job_totals": "Job Totals Only", + "work_authorization": "Work Authorization" }, "labels": { + "misc": "Miscellaneous Documents", + "repairorder": "Repair Order Related", "title": "Print Center" } }, diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index f539b1138..4cfc21747 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -737,9 +737,17 @@ "nocontexttype": "" }, "jobs": { - "repairorder": "" + "appointment_reminder": "", + "casl_work_authorization": "", + "coversheet": "", + "estimate_detail": "", + "fippa_work_authorization": "", + "job_totals": "", + "work_authorization": "" }, "labels": { + "misc": "", + "repairorder": "", "title": "" } }, diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 2a0141fa2..86909780d 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -737,9 +737,17 @@ "nocontexttype": "" }, "jobs": { - "repairorder": "" + "appointment_reminder": "", + "casl_work_authorization": "", + "coversheet": "", + "estimate_detail": "", + "fippa_work_authorization": "", + "job_totals": "", + "work_authorization": "" }, "labels": { + "misc": "", + "repairorder": "", "title": "" } }, diff --git a/client/src/utils/RenderTemplate.js b/client/src/utils/RenderTemplate.js new file mode 100644 index 000000000..ca40944dc --- /dev/null +++ b/client/src/utils/RenderTemplate.js @@ -0,0 +1,37 @@ +import { gql } from "apollo-boost"; +import { QUERY_TEMPLATES_BY_NAME } from "../graphql/templates.queries"; +import axios from "axios"; + +export default async function RenderTemplate(templateObject, client, bodyshop) { + const { data: templateRecords } = await client.query({ + query: QUERY_TEMPLATES_BY_NAME, + variables: { name: templateObject.name }, + fetchPolicy: "network-only", + }); + + let templateToUse; + + if (templateRecords.templates.length === 1) { + templateToUse = templateRecords.templates[0]; + } else if (templateRecords.templates.length === 2) { + templateToUse = templateRecords.templates.filter((t) => !!t.bodyshopid); + } else { + //No template found.Uh oh. + alert("Template key does not exist."); + throw new Error("Template key does not exist."); + } + + const { data: contextData } = await client.query({ + query: gql(templateToUse.query), + variables: { ...templateObject.variables }, + fetchPolicy: "network-only", + }); + + const { data } = await axios.post("/render", { + view: templateToUse.html, + context: { ...contextData, bodyshop: bodyshop }, + }); + return new Promise((resolve, reject) => { + resolve(data); + }); +}