From 9a60149d7559d2ad4ecd0d74713c041ab1e578c1 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Tue, 20 Jul 2021 10:34:03 -0700 Subject: [PATCH 1/2] IO-1266 attach pdf copy of email. --- bodyshop_translations.babel | 21 +++++ .../email-overlay/email-overlay.container.jsx | 72 ++++++++++----- .../shop-info/shop-info.general.component.jsx | 8 ++ client/src/graphql/bodyshop.queries.js | 2 + client/src/translations/en_us/common.json | 1 + client/src/translations/es/common.json | 1 + client/src/translations/fr/common.json | 1 + client/src/utils/RenderTemplate.js | 18 +++- .../down.yaml | 5 ++ .../up.yaml | 6 ++ .../down.yaml | 87 ++++++++++++++++++ .../up.yaml | 88 +++++++++++++++++++ .../down.yaml | 79 +++++++++++++++++ .../up.yaml | 80 +++++++++++++++++ hasura/migrations/metadata.yaml | 2 + server/email/sendemail.js | 3 +- 16 files changed, 451 insertions(+), 23 deletions(-) create mode 100644 hasura/migrations/1626795754549_alter_table_public_bodyshops_add_column_attach_pdf_to_email/down.yaml create mode 100644 hasura/migrations/1626795754549_alter_table_public_bodyshops_add_column_attach_pdf_to_email/up.yaml create mode 100644 hasura/migrations/1626795768315_update_permission_user_public_table_bodyshops/down.yaml create mode 100644 hasura/migrations/1626795768315_update_permission_user_public_table_bodyshops/up.yaml create mode 100644 hasura/migrations/1626795775694_update_permission_user_public_table_bodyshops/down.yaml create mode 100644 hasura/migrations/1626795775694_update_permission_user_public_table_bodyshops/up.yaml diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 3bc1ff5f1..46f5e9f32 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -3014,6 +3014,27 @@ + + attach_pdf_to_email + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + bill_federal_tax_rate false diff --git a/client/src/components/email-overlay/email-overlay.container.jsx b/client/src/components/email-overlay/email-overlay.container.jsx index e776a156e..f931728d9 100644 --- a/client/src/components/email-overlay/email-overlay.container.jsx +++ b/client/src/components/email-overlay/email-overlay.container.jsx @@ -43,6 +43,10 @@ export function EmailOverlayContainer({ const [loading, setLoading] = useState(false); const [sending, setSending] = useState(false); const [rawHtml, setRawHtml] = useState(""); + const [pdfCopytoAttach, setPdfCopytoAttach] = useState({ + filename: null, + pdf: null, + }); const [selectedMedia, setSelectedMedia] = useState([]); const defaultEmailFrom = { @@ -59,17 +63,17 @@ export function EmailOverlayContainer({ const handleFinish = async (values) => { logImEXEvent("email_send_from_modal"); - const attachments = []; + //const attachments = []; - if (values.fileList) - await asyncForEach(values.fileList, async (f) => { - const t = { - ContentType: f.type, - Filename: f.name, - Base64Content: (await toBase64(f.originFileObj)).split(",")[1], - }; - attachments.push(t); - }); + // if (values.fileList) + // await asyncForEach(values.fileList, async (f) => { + // const t = { + // ContentType: f.type, + // Filename: f.name, + // Base64Content: (await toBase64(f.originFileObj)).split(",")[1], + // }; + // attachments.push(t); + // }); setSending(true); try { @@ -77,11 +81,28 @@ export function EmailOverlayContainer({ ...defaultEmailFrom, ...values, html: rawHtml, - attachments: - values.fileList && - (await Promise.all( - values.fileList.map(async (f) => await toBase64(f.originFileObj)) - )), + attachments: [ + ...(values.fileList + ? await Promise.all( + values.fileList.map(async (f) => { + return { + filename: f.name, + path: await toBase64(f.originFileObj), + }; + }) + ) + : []), + ...(pdfCopytoAttach.pdf + ? [ + { + path: pdfCopytoAttach.pdf, + filename: + pdfCopytoAttach.filename && + `${pdfCopytoAttach.filename}.pdf`, + }, + ] + : []), + ], media: selectedMedia.filter((m) => m.isSelected).map((m) => m.src), //attachments, }); @@ -99,13 +120,22 @@ export function EmailOverlayContainer({ const render = async () => { logImEXEvent("email_render_template", { template: emailConfig.template }); setLoading(true); - let html = await RenderTemplate(emailConfig.template, bodyshop, true); + let { html, pdf, filename } = await RenderTemplate( + emailConfig.template, + bodyshop, + true + ); const response = await axios.post("/render/inlinecss", { html: html, url: `${window.location.protocol}://${window.location.host}/`, }); setRawHtml(response.data); + + if (pdf) { + setPdfCopytoAttach({ pdf, filename }); + } + form.setFieldsValue({ ...emailConfig.messageOptions, cc: @@ -166,8 +196,8 @@ const toBase64 = (file) => reader.onerror = (error) => reject(error); }); -const asyncForEach = async (array, callback) => { - for (let index = 0; index < array.length; index++) { - await callback(array[index], index, array); - } -}; +// 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/shop-info/shop-info.general.component.jsx b/client/src/components/shop-info/shop-info.general.component.jsx index d7b40f1d8..26a92dcab 100644 --- a/client/src/components/shop-info/shop-info.general.component.jsx +++ b/client/src/components/shop-info/shop-info.general.component.jsx @@ -436,6 +436,14 @@ export default function ShopInfoGeneral({ form }) { > + + + + diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js index 3916c029e..0b65d35d8 100644 --- a/client/src/graphql/bodyshop.queries.js +++ b/client/src/graphql/bodyshop.queries.js @@ -91,6 +91,7 @@ export const QUERY_BODYSHOP = gql` md_jobline_presets cdk_dealerid features + attach_pdf_to_email employees { id active @@ -178,6 +179,7 @@ export const UPDATE_SHOP = gql` jc_hourly_rates md_jobline_presets cdk_dealerid + attach_pdf_to_email employees { id first_name diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 20653eb85..8c444c2cd 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -199,6 +199,7 @@ "label": "Label" }, "appt_length": "Default Appointment Length", + "attach_pdf_to_email": "Attach PDF copy to sent emails?", "bill_federal_tax_rate": "Bills - Federal Tax Rate %", "bill_local_tax_rate": "Bill - Provincial/State Tax Rate %", "bill_state_tax_rate": "Bill - Provincial/State Tax Rate %", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 2b093063c..d8eb746a4 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -199,6 +199,7 @@ "label": "" }, "appt_length": "", + "attach_pdf_to_email": "", "bill_federal_tax_rate": "", "bill_local_tax_rate": "", "bill_state_tax_rate": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index a25172c23..811471037 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -199,6 +199,7 @@ "label": "" }, "appt_length": "", + "attach_pdf_to_email": "", "bill_federal_tax_rate": "", "bill_local_tax_rate": "", "bill_state_tax_rate": "", diff --git a/client/src/utils/RenderTemplate.js b/client/src/utils/RenderTemplate.js index 1e886fcdc..78452b1b6 100644 --- a/client/src/utils/RenderTemplate.js +++ b/client/src/utils/RenderTemplate.js @@ -8,6 +8,7 @@ import { setEmailOptions } from "../redux/email/email.actions"; import { store } from "../redux/store"; import client from "../utils/GraphQLClient"; import { TemplateList } from "./TemplateConstants"; +import _ from "lodash"; const server = process.env.REACT_APP_REPORTS_SERVER_URL; jsreport.serverUrl = server; @@ -39,8 +40,10 @@ export default async function RenderTemplate( offset: moment().utcOffset(), }, }; + try { const render = await jsreport.renderAsync(reportRequest); + if (!renderAsHtml) { render.download( (Templates[templateObject.name] && @@ -48,8 +51,21 @@ export default async function RenderTemplate( "" ); } else { + let pdf; + if (bodyshop.attach_pdf_to_email) { + const pdfRequest = _.cloneDeep(reportRequest); + pdfRequest.template.recipe = "chrome-pdf"; + const pdfRender = await jsreport.renderAsync(pdfRequest); + pdf = pdfRender.toDataURI(); + } return new Promise((resolve, reject) => { - resolve(render.toString()); + resolve({ + pdf, + filename: + Templates[templateObject.name] && + Templates[templateObject.name].title, + html: render.toString(), + }); }); } } catch (error) { diff --git a/hasura/migrations/1626795754549_alter_table_public_bodyshops_add_column_attach_pdf_to_email/down.yaml b/hasura/migrations/1626795754549_alter_table_public_bodyshops_add_column_attach_pdf_to_email/down.yaml new file mode 100644 index 000000000..611f63c09 --- /dev/null +++ b/hasura/migrations/1626795754549_alter_table_public_bodyshops_add_column_attach_pdf_to_email/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."bodyshops" DROP COLUMN "attach_pdf_to_email"; + type: run_sql diff --git a/hasura/migrations/1626795754549_alter_table_public_bodyshops_add_column_attach_pdf_to_email/up.yaml b/hasura/migrations/1626795754549_alter_table_public_bodyshops_add_column_attach_pdf_to_email/up.yaml new file mode 100644 index 000000000..0730da959 --- /dev/null +++ b/hasura/migrations/1626795754549_alter_table_public_bodyshops_add_column_attach_pdf_to_email/up.yaml @@ -0,0 +1,6 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."bodyshops" ADD COLUMN "attach_pdf_to_email" boolean + NOT NULL DEFAULT False; + type: run_sql diff --git a/hasura/migrations/1626795768315_update_permission_user_public_table_bodyshops/down.yaml b/hasura/migrations/1626795768315_update_permission_user_public_table_bodyshops/down.yaml new file mode 100644 index 000000000..24984ef56 --- /dev/null +++ b/hasura/migrations/1626795768315_update_permission_user_public_table_bodyshops/down.yaml @@ -0,0 +1,87 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - accountingconfig + - address1 + - address2 + - appt_alt_transport + - appt_colors + - appt_length + - bill_tax_rates + - cdk_dealerid + - city + - country + - created_at + - default_adjustment_rate + - deliverchecklist + - email + - enforce_class + - enforce_referral + - features + - federal_tax_id + - id + - imexshopid + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - jc_hourly_rates + - jobsizelimit + - logo_img_path + - md_categories + - md_ccc_rates + - md_classes + - md_hour_split + - md_ins_cos + - md_jobline_presets + - md_labor_rates + - md_messaging_presets + - md_notes_presets + - md_order_statuses + - md_parts_locations + - md_payment_types + - md_rbac + - md_referral_sources + - md_responsibility_centers + - md_ro_statuses + - messagingservicesid + - phone + - prodtargethrs + - production_config + - region_config + - schedule_end_time + - schedule_start_time + - scoreboard_target + - shopname + - shoprates + - speedprint + - ssbuckets + - state + - state_tax_id + - stripe_acct_id + - sub_status + - target_touchtime + - template_header + - textid + - updated_at + - use_fippa + - website + - workingdays + - zip_post + computed_fields: [] + filter: + associations: + user: + authid: + _eq: X-Hasura-User-Id + role: user + table: + name: bodyshops + schema: public + type: create_select_permission diff --git a/hasura/migrations/1626795768315_update_permission_user_public_table_bodyshops/up.yaml b/hasura/migrations/1626795768315_update_permission_user_public_table_bodyshops/up.yaml new file mode 100644 index 000000000..c8a09ddd4 --- /dev/null +++ b/hasura/migrations/1626795768315_update_permission_user_public_table_bodyshops/up.yaml @@ -0,0 +1,88 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - accountingconfig + - address1 + - address2 + - appt_alt_transport + - appt_colors + - appt_length + - attach_pdf_to_email + - bill_tax_rates + - cdk_dealerid + - city + - country + - created_at + - default_adjustment_rate + - deliverchecklist + - email + - enforce_class + - enforce_referral + - features + - federal_tax_id + - id + - imexshopid + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - jc_hourly_rates + - jobsizelimit + - logo_img_path + - md_categories + - md_ccc_rates + - md_classes + - md_hour_split + - md_ins_cos + - md_jobline_presets + - md_labor_rates + - md_messaging_presets + - md_notes_presets + - md_order_statuses + - md_parts_locations + - md_payment_types + - md_rbac + - md_referral_sources + - md_responsibility_centers + - md_ro_statuses + - messagingservicesid + - phone + - prodtargethrs + - production_config + - region_config + - schedule_end_time + - schedule_start_time + - scoreboard_target + - shopname + - shoprates + - speedprint + - ssbuckets + - state + - state_tax_id + - stripe_acct_id + - sub_status + - target_touchtime + - template_header + - textid + - updated_at + - use_fippa + - website + - workingdays + - zip_post + computed_fields: [] + filter: + associations: + user: + authid: + _eq: X-Hasura-User-Id + role: user + table: + name: bodyshops + schema: public + type: create_select_permission diff --git a/hasura/migrations/1626795775694_update_permission_user_public_table_bodyshops/down.yaml b/hasura/migrations/1626795775694_update_permission_user_public_table_bodyshops/down.yaml new file mode 100644 index 000000000..b09c84f9e --- /dev/null +++ b/hasura/migrations/1626795775694_update_permission_user_public_table_bodyshops/down.yaml @@ -0,0 +1,79 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_update_permission +- args: + permission: + columns: + - accountingconfig + - address1 + - address2 + - appt_alt_transport + - appt_colors + - appt_length + - bill_tax_rates + - city + - country + - created_at + - default_adjustment_rate + - deliverchecklist + - email + - enforce_class + - enforce_referral + - federal_tax_id + - id + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - jc_hourly_rates + - logo_img_path + - md_categories + - md_ccc_rates + - md_classes + - md_hour_split + - md_ins_cos + - md_jobline_presets + - md_labor_rates + - md_messaging_presets + - md_notes_presets + - md_order_statuses + - md_parts_locations + - md_payment_types + - md_rbac + - md_referral_sources + - md_responsibility_centers + - md_ro_statuses + - phone + - prodtargethrs + - production_config + - schedule_end_time + - schedule_start_time + - scoreboard_target + - shopname + - shoprates + - speedprint + - ssbuckets + - state + - state_tax_id + - target_touchtime + - updated_at + - use_fippa + - website + - workingdays + - zip_post + filter: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + set: {} + role: user + table: + name: bodyshops + schema: public + type: create_update_permission diff --git a/hasura/migrations/1626795775694_update_permission_user_public_table_bodyshops/up.yaml b/hasura/migrations/1626795775694_update_permission_user_public_table_bodyshops/up.yaml new file mode 100644 index 000000000..adce758ee --- /dev/null +++ b/hasura/migrations/1626795775694_update_permission_user_public_table_bodyshops/up.yaml @@ -0,0 +1,80 @@ +- args: + role: user + table: + name: bodyshops + schema: public + type: drop_update_permission +- args: + permission: + columns: + - accountingconfig + - address1 + - address2 + - appt_alt_transport + - appt_colors + - appt_length + - attach_pdf_to_email + - bill_tax_rates + - city + - country + - created_at + - default_adjustment_rate + - deliverchecklist + - email + - enforce_class + - enforce_referral + - federal_tax_id + - id + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - jc_hourly_rates + - logo_img_path + - md_categories + - md_ccc_rates + - md_classes + - md_hour_split + - md_ins_cos + - md_jobline_presets + - md_labor_rates + - md_messaging_presets + - md_notes_presets + - md_order_statuses + - md_parts_locations + - md_payment_types + - md_rbac + - md_referral_sources + - md_responsibility_centers + - md_ro_statuses + - phone + - prodtargethrs + - production_config + - schedule_end_time + - schedule_start_time + - scoreboard_target + - shopname + - shoprates + - speedprint + - ssbuckets + - state + - state_tax_id + - target_touchtime + - updated_at + - use_fippa + - website + - workingdays + - zip_post + filter: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + set: {} + role: user + table: + name: bodyshops + schema: public + type: create_update_permission diff --git a/hasura/migrations/metadata.yaml b/hasura/migrations/metadata.yaml index 3481eec42..bd0c4200f 100644 --- a/hasura/migrations/metadata.yaml +++ b/hasura/migrations/metadata.yaml @@ -756,6 +756,7 @@ tables: - appt_alt_transport - appt_colors - appt_length + - attach_pdf_to_email - bill_tax_rates - cdk_dealerid - city @@ -831,6 +832,7 @@ tables: - appt_alt_transport - appt_colors - appt_length + - attach_pdf_to_email - bill_tax_rates - city - country diff --git a/server/email/sendemail.js b/server/email/sendemail.js index 6f54b00f1..39acfaeac 100644 --- a/server/email/sendemail.js +++ b/server/email/sendemail.js @@ -48,7 +48,8 @@ exports.sendEmail = async (req, res) => { ...((req.body.attachments && req.body.attachments.map((a) => { return { - path: a, + filename: a.filename, + path: a.path, }; })) || []), From 3e1663bf18c0e31c5db3e20dea3c200e214cc1e4 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Tue, 20 Jul 2021 10:36:49 -0700 Subject: [PATCH 2/2] IO-1267 missing query info in detail cards. --- client/src/graphql/jobs.queries.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index 7a8974a5b..8bbcc6e1a 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -689,6 +689,8 @@ export const QUERY_JOB_CARD_DETAILS = gql` v_make_desc v_model_desc v_color + v_vin + plate_st plate_no vehicle { id