diff --git a/_reference/JSReportSetup.md b/_reference/JSReportSetup.md new file mode 100644 index 000000000..66c0f542c --- /dev/null +++ b/_reference/JSReportSetup.md @@ -0,0 +1,40 @@ +# install node.js +wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash +# you may need to reopen terminal +nvm install 8.11.3 + +mkdir jsreportapp +cd jsreportapp +npm i -g jsreport-cli +jsreport init +jsreport configure + +# chrome dependencies +sudo apt-get install -y libgconf-2-4 +sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - +sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' +sudo apt-get update +sudo apt-get install -y google-chrome-unstable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst --no-install-recommends + +# on ubuntu 20 run also +sudo apt-get install -y libxtst6 libxss1 + +# start jsreport to see it running on port 5488 +jsreport start + +# the next steps are optional to start jsreport on boot +npm install pm2 -g +pm2 start server.js +pm2 startup +# run the output of previous command + +# optionally if you want to use older phantomjs for pdf rendering +sudo apt-get install -y --no-install-recommends gnupg git curl wget ca-certificates +sudo apt-get install -y --no-install-recommends xfonts-base xfonts-75dpi +npm i jsreport-phantom-pdf --save --save-exact + +Running on port 80 and 443 without SU +$ setcap 'cap_net_bind_service=+ep' /path/to/.nvm/v0.10.17/bin/node +$ apt-get remove nginx +$ cd /path/to/app +$ PORT=80 node app \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 1a2f1e0b6..1e33e6136 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12390,6 +12390,11 @@ "verror": "1.10.0" } }, + "jsreport-browser-client-dist": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsreport-browser-client-dist/-/jsreport-browser-client-dist-1.3.0.tgz", + "integrity": "sha512-E83cVmxQ5np3rxns6dhFu15m5kZ5yXJDIyfbHjLPxO0AZXVQOuMrdvYsUCj+j/ZSaiROoBCstZRO7pa4HmZNGw==" + }, "jsx-ast-utils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.1.0.tgz", diff --git a/client/package.json b/client/package.json index e243b2b5c..b2ba1d2cc 100644 --- a/client/package.json +++ b/client/package.json @@ -25,6 +25,7 @@ "i18next-browser-languagedetector": "^6.0.1", "jsoneditor": "^9.1.7", "jsoneditor-react": "^3.1.0", + "jsreport-browser-client-dist": "^1.3.0", "logrocket": "^1.0.13", "moment-business-days": "^1.2.0", "node-sass": "^4.14.1", diff --git a/client/public/render-styles.css b/client/public/render-styles.css deleted file mode 100644 index fbaa9e27f..000000000 --- a/client/public/render-styles.css +++ /dev/null @@ -1,58 +0,0 @@ -body { - font-family: "Open Sans", sans-serif; - line-height: 1.25; - padding: 10mm 10mm 10mm 10mm !important; -} - -@page { - margin: 50px; -} - -table.imex-table { - border: 1px solid #ccc; - border-collapse: collapse; - margin: 0; - padding: 0; - width: 100%; - table-layout: fixed; - font-size: inherit; - - page-break-inside: auto; -} - -table.imex-table caption { - /* font-size: 1.5em; */ - margin: 0.5em 0 0.75em; - font-size: inherit; -} - -table.imex-table tr { - /* background-color: #f8f8f8; */ - border: 1px solid #ddd; - padding: 0.2rem; - font-size: inherit; - - page-break-inside: avoid; - page-break-after: auto; -} - -table.imex-table th, -table.imex-table td { - padding: 0.3rem; - text-align: center; - font-size: inherit; -} -table.imex-table th.left, -table.imex-table td.left { - padding: 0.3rem; - text-align: left; - font-size: inherit; -} - -table.imex-table th { - /* font-size: 0.85em; */ - letter-spacing: 0.1em; - text-transform: uppercase; - - /* display: table-header-group; */ -} diff --git a/client/src/components/email-overlay/email-overlay.container.jsx b/client/src/components/email-overlay/email-overlay.container.jsx index 9432380c5..675e14b3e 100644 --- a/client/src/components/email-overlay/email-overlay.container.jsx +++ b/client/src/components/email-overlay/email-overlay.container.jsx @@ -109,11 +109,18 @@ export function EmailOverlayContainer({ const render = async () => { logImEXEvent("email_render_template", { template: emailConfig.template }); setLoading(true); - let html = await RenderTemplate(emailConfig.template, bodyshop); + let html = await RenderTemplate(emailConfig.template, bodyshop, true); + + const response = await axios.post("/render/inlinecss", { + html: html, + url: `${window.location.protocol}://${window.location.host}/`, + }); + + console.log("response", response); setMessageOptions({ ...emailConfig.messageOptions, ...defaultEmailFrom, - html: html, + html: response.data, fileList: [], }); setLoading(false); diff --git a/client/src/components/print-center-item/print-center-item.component.jsx b/client/src/components/print-center-item/print-center-item.component.jsx index 8730fe3ab..4879a7b56 100644 --- a/client/src/components/print-center-item/print-center-item.component.jsx +++ b/client/src/components/print-center-item/print-center-item.component.jsx @@ -25,14 +25,14 @@ export function PrintCenterItemComponent({ disabled, }) { const renderToNewWindow = async () => { - const html = await RenderTemplate( + await RenderTemplate( { name: item.key, variables: { id: id }, }, bodyshop ); - displayTemplateInWindow(html); + // displayTemplateInWindow(html); }; if (disabled) return
  • {item.title}
  • ; diff --git a/client/src/components/shop-template-editor-save-button/shop-template-editor-save-button.component.jsx b/client/src/components/shop-template-editor-save-button/shop-template-editor-save-button.component.jsx index 692b19308..878c40305 100644 --- a/client/src/components/shop-template-editor-save-button/shop-template-editor-save-button.component.jsx +++ b/client/src/components/shop-template-editor-save-button/shop-template-editor-save-button.component.jsx @@ -22,11 +22,7 @@ export default function ShopTemplateSaveButton({ html: data.html, url: `${window.location.protocol}://${window.location.host}/`, }); - console.log( - "🚀 ~ file: shop-template-editor-save-button.component.jsx ~ line 25 ~ emailEditorRef.current.exportHtml ~ inlineHtml", - response - ); - + const result = await updateTemplate({ variables: { templateId: templateId, diff --git a/client/src/debug.log b/client/src/debug.log index a56efb4ec..6e8ec3bc1 100644 --- a/client/src/debug.log +++ b/client/src/debug.log @@ -2,3 +2,5 @@ [1008/114603.993:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3) [1008/121110.259:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3) [1008/122424.146:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3) +[0106/150233.556:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3) +[0106/152014.936:ERROR:directory_reader_win.cc(43)] FindFirstFile: The system cannot find the path specified. (0x3) diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js index 695d6885c..7ccf0b3fc 100644 --- a/client/src/graphql/bodyshop.queries.js +++ b/client/src/graphql/bodyshop.queries.js @@ -74,6 +74,7 @@ export const QUERY_BODYSHOP = gql` appt_alt_transport schedule_start_time schedule_end_time + imexshopid employees { id first_name @@ -145,7 +146,8 @@ export const UPDATE_SHOP = gql` appt_colors appt_alt_transport schedule_start_time - schedule_end_time + schedule_end_time + imexshopid employees { id first_name diff --git a/client/src/utils/RenderTemplate.js b/client/src/utils/RenderTemplate.js index 0f91bed13..49034bf89 100644 --- a/client/src/utils/RenderTemplate.js +++ b/client/src/utils/RenderTemplate.js @@ -1,43 +1,90 @@ -import axios from "axios"; import gql from "graphql-tag"; -import { QUERY_TEMPLATES_BY_NAME } from "../graphql/templates.queries"; +import jsreport from "jsreport-browser-client-dist"; import client from "../utils/GraphQLClient"; +import cleanAxios from "./CleanAxios"; -export default async function RenderTemplate(templateObject, bodyshop) { - const { data: templateRecords } = await client.query({ - query: QUERY_TEMPLATES_BY_NAME, - variables: { name: templateObject.name }, - fetchPolicy: "network-only", - }); +const server = "https://reports.bodyshop.app"; +jsreport.serverUrl = server; +jsreport.headers["Authorization"] = "Basic " + btoa("admin:admin"); - let templateToUse; +export default async function RenderTemplate( + templateObject, + bodyshop, + renderAsHtml = false +) { + //Template Object + // { + // name: TemplateList().parts_order_confirmation.key, + // variables: { + // id: insertResult.data.insert_parts_orders.returning[0].id, + // }, + // }, - if (templateRecords.templates.length === 1) { - console.log("[ITE] Using OOTB template."); - templateToUse = templateRecords.templates[0]; - } else if (templateRecords.templates.length === 2) { - console.log("[ITE] Found custom template."); - templateToUse = templateRecords.templates.filter((t) => !!t.bodyshopid)[0]; - console.log("templateToUse", templateToUse); + //Query assets that match the template name. Must be in format <>.query + const jsReportQueries = await cleanAxios.get( + `${server}/odata/assets?$filter=name eq '${templateObject.name}.query'`, + { headers: { Authorization: "Basic " + btoa("admin:admin") } } + ); + + let templateQueryToExecute, + useShopSpecificTemplate = false; + if (jsReportQueries.data.value.length === 0) { + //We have no query to execute. Just render the template. + } else if (jsReportQueries.data.value.length === 1) { + //We're using the default template. Get the query and execute. + templateQueryToExecute = atob(jsReportQueries.data.value[0].content); + } else if (jsReportQueries.data.value.length === 2) { + //There's a custom template. Use that query instead and execute. We find it because it has a parent folder. + templateQueryToExecute = atob( + jsReportQueries.data.value.filter((v) => !!v.folder)[0].content + ); + useShopSpecificTemplate = true; } else { - //No template found.Uh oh. - alert("Error: Template key does not exist."); - throw new Error("Template key does not exist."); + //We have too many queries to choose from. Throw an error. + alert( + "There are too many queries to choose from. Please ensure there are no conflicting keys." + ); + throw new Error( + "There are too many queries to choose from. Please ensure there are no conflicting keys." + ); } - const { data: contextData } = await client.query({ - query: gql(templateToUse.query), + query: gql(templateQueryToExecute), 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); - }); + let reportRequest = { + template: { + name: useShopSpecificTemplate + ? `/${bodyshop.imexshopid}/${templateObject.name}` + : `/${templateObject.name}`, + ...(renderAsHtml ? {} : { recipe: "chrome-pdf" }), + }, + data: { + ...contextData, + headerpath: `/${bodyshop.imexshopid}/header.html`, + bodyshop: bodyshop, + }, + }; + const render = await jsreport.renderAsync(reportRequest); + + if (!renderAsHtml) { + render.download(); + var html = + "" + + "" + + "" + + '' + + ""; + displayTemplateInWindowNoprint(html); + } else { + return new Promise((resolve, reject) => { + resolve(render.toString()); + }); + } } export const displayTemplateInWindow = (html) => { diff --git a/client/src/utils/TemplateConstants.js b/client/src/utils/TemplateConstants.js index c410e92ff..e9bfd2bd3 100644 --- a/client/src/utils/TemplateConstants.js +++ b/client/src/utils/TemplateConstants.js @@ -14,97 +14,5 @@ export const TemplateList = (type, object) => { drivingId: "job", key: "estimate_detail", }, - all_job_notes: { - title: i18n.t("printcenter.jobs.all_job_notes"), - description: "All jobs Notes including Private", - drivingId: "job", - key: "all_job_notes", - }, - fippa_authorization: { - title: i18n.t("printcenter.jobs.fippa_authorization"), - description: "FIPPA Work Auth", - drivingId: "job", - key: "fippa_authorization", - }, - casl_authorization: { - title: i18n.t("printcenter.jobs.casl_authorization"), - description: "CASL Auth", - drivingId: "job", - key: "casl_authorization", - }, - window_tag: { - title: i18n.t("printcenter.jobs.window_tag"), - description: "Window Tag", - drivingId: "job", - key: "window_tag", - }, - cover_sheet: { - title: i18n.t("printcenter.jobs.cover_sheet"), - description: "Cover Sheet", - drivingId: "job", - key: "cover_sheet", - }, - - time_tickets_by_employee: { - title: "Time Tickets by Employee", - description: "Time tickets for employee with date range", - drivingId: "employee", - key: "time_tickets_by_employee", - }, - - //Non Completed Items - appointment_reminder: { - title: "Appointment Reminder", - description: - "Sent to a customer as a reminder of an upcoming appointment.", - drivingId: "appointment", - key: "appointment_reminder", - subject: `Appointment Reminder`, - }, - appointment_confirmation: { - title: "Appointment Confirmation", - description: - "Sent to a customer as a Confirmation of an upcoming appointment.", - drivingId: "appointment", - key: "appointment_confirmation", - }, - parts_order_confirmation: { - title: "Parts Order Confirmation", - description: "Parts order template including part details", - drivingId: "partsorder", - key: "parts_order_confirmation", - subject: `Parts Order for ${object}`, - }, - - cover_sheet_landscape: { - title: "Cover Sheet - Landscape", - description: "Cover sheet landscape", - drivingId: "job", - key: "cover_sheet_landscape", - }, - cover_sheet_portrait: { - title: "Cover Sheet - portrait", - description: "Cover sheet portrait", - drivingId: "job", - key: "cover_sheet_portrait", - }, - parts_return_confirmation: { - title: "Parts Return Confirmation", - description: "Parts Return template including part details", - drivingId: "partsorder", - key: "parts_return_confirmation", - }, - csi_invitation: { - title: "Customer Survey Invitation", - description: "Customer Survey Invitation", - drivingId: "csi", - key: "csi_invitation", - }, - payment_receipt: { - title: "Payment Receipt", - description: "Receipt of payment for customer", - drivingId: "payment", - key: "payment_receipt", - }, }; }; diff --git a/client/templates/appointment_confirmation/appointment_confirmation.query.gql b/client/templates/appointment_confirmation/appointment_confirmation.query.gql deleted file mode 100644 index 6e1c4f5a9..000000000 --- a/client/templates/appointment_confirmation/appointment_confirmation.query.gql +++ /dev/null @@ -1,11 +0,0 @@ -query EMAIL_APPOINTMENT_CONFIRMATION($id: uuid!) { - appointments_by_pk(id: $id) { - start - title - job { - ownr_fn - ownr_ln - ownr_ea - } - } -} diff --git a/client/templates/appointment_confirmation/appointment_confirmation.template.html b/client/templates/appointment_confirmation/appointment_confirmation.template.html deleted file mode 100644 index 5aa9669c7..000000000 --- a/client/templates/appointment_confirmation/appointment_confirmation.template.html +++ /dev/null @@ -1,9 +0,0 @@ -
    -

    Hello {{appointments_by_pk.job.ownr_fn}},

    -

    - This is a confirmation that you have an appointment at - {{appointments_by_pk.start}} to bring your car in for repair. Please email - us at {{bodyshop.email}} if you can't make it.  -

    -
    - \ No newline at end of file diff --git a/client/templates/appointment_reminder/appointment_reminder.query.gql b/client/templates/appointment_reminder/appointment_reminder.query.gql deleted file mode 100644 index 6e1c4f5a9..000000000 --- a/client/templates/appointment_reminder/appointment_reminder.query.gql +++ /dev/null @@ -1,11 +0,0 @@ -query EMAIL_APPOINTMENT_CONFIRMATION($id: uuid!) { - appointments_by_pk(id: $id) { - start - title - job { - ownr_fn - ownr_ln - ownr_ea - } - } -} diff --git a/client/templates/appointment_reminder/appointment_reminder.template.html b/client/templates/appointment_reminder/appointment_reminder.template.html deleted file mode 100644 index 705bb3e20..000000000 --- a/client/templates/appointment_reminder/appointment_reminder.template.html +++ /dev/null @@ -1,8 +0,0 @@ -
    -

    Hello {{appointments_by_pk.job.ownr_fn}},

    -

    - This is a reminder that you have an appointment at - {{appointments_by_pk.start}} to bring your car in for repair. Please email - us at {{bodyshop.email}} if you can't make it.  -

    -
    diff --git a/client/templates/csi_invitation/csi_invitation.query.gql b/client/templates/csi_invitation/csi_invitation.query.gql deleted file mode 100644 index 0dacda99a..000000000 --- a/client/templates/csi_invitation/csi_invitation.query.gql +++ /dev/null @@ -1,6 +0,0 @@ -query ($id: uuid!){ - csi_by_pk(id: $id){ - id - relateddata - } -} \ No newline at end of file diff --git a/client/templates/csi_invitation/csi_invitation.template.html b/client/templates/csi_invitation/csi_invitation.template.html deleted file mode 100644 index ba8b22f31..000000000 --- a/client/templates/csi_invitation/csi_invitation.template.html +++ /dev/null @@ -1,45 +0,0 @@ -
    Hi {{csi_by_pk.relateddata.job.ownr_fn}}, 
    -
     
    -
    - Thank you for getting your car repaired at - {{csi_by_pk.relateddata.bodyshop.shopname}}. We invite you to complete a - survey about your experience.  -
    -
     
    - - - - - - -
    - - - - - - -
    - Complete Survey → -
    -
    -
     
    diff --git a/client/templates/estimate_detail/estimate_detail.query.gql b/client/templates/estimate_detail/estimate_detail.query.gql deleted file mode 100644 index f0a2d7657..000000000 --- a/client/templates/estimate_detail/estimate_detail.query.gql +++ /dev/null @@ -1,32 +0,0 @@ -query TEMPLATE_ESTIMATE_DETAIL($id: uuid!) { - jobs_by_pk(id: $id) { - csr - ded_amt - ded_status - id - ownr_co_nm - ownr_ln - ownr_fn - plate_no - plate_st - ro_number - regie_number - tlos_ind - v_color - v_make_desc - v_model_desc - v_model_yr - v_vin - clm_no - joblines(order_by: { line_no: asc }) { - id - mod_lbr_ty - mod_lb_hrs - part_qty - oem_partno - op_code_desc - line_desc - line_no - } - } -} diff --git a/client/templates/estimate_detail/estimate_detail.template.html b/client/templates/estimate_detail/estimate_detail.template.html deleted file mode 100644 index e30a11457..000000000 --- a/client/templates/estimate_detail/estimate_detail.template.html +++ /dev/null @@ -1,87 +0,0 @@ -
    -

    - Job Detail Summary -

    - - - - - - - - -
    - Owner: {{jobs_by_pk.ownr_fn}} {{jobs_by_pk.ownr_ln}} - {{jobs_by_pk.ownr_co_nm}} - - Vehicle: {{jobs_by_pk.v_model_yr}} - {{jobs_by_pk.v_color}}{{jobs_by_pk.v_make_desc}} - {{jobs_by_pk.v_model_desc}} - -

    - Claim Number: {{jobs_by_pk.clm_no}}
    Regie Number:</strong > {{jobs_by_pk.regie_number}} - -

    -

    - Deductible: {{jobs_by_pk.ded_amt}} - {{jobs_by_pk.ded_status}} -

    -
    -

    Job Lines

    - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Line No. - - Line Desc. - - OEM Part # - - Qty. - - Labor Type - - Hours -
    - {{#each jobs_by_pk.joblines}} -
    - {{this.line_no}} - - {{this.line_desc}} - - {{this.oem_partno}} - - {{this.part_qty}} - - {{this.mod_lbr_ty}} - - {{this.mod_lb_hrs}} -
    {{/each}}
    -
    diff --git a/client/templates/helpers.md b/client/templates/helpers.md deleted file mode 100644 index 1464c021b..000000000 --- a/client/templates/helpers.md +++ /dev/null @@ -1,3 +0,0 @@ -Table Styles - - diff --git a/client/templates/parts_order_confirmation/parts_order_confirmation.query.gql b/client/templates/parts_order_confirmation/parts_order_confirmation.query.gql deleted file mode 100644 index 6558056b0..000000000 --- a/client/templates/parts_order_confirmation/parts_order_confirmation.query.gql +++ /dev/null @@ -1,29 +0,0 @@ -query REPORT_QUERY_PARTS_ORDER_BY_PK($id: uuid!) { - parts_orders_by_pk(id: $id) { - job { - id - vehicle { - id - v_model_desc - v_make_desc - v_model_yr - v_vin - } - ro_number - est_number - } - id - deliver_by - parts_order_lines { - id - db_price - act_price - line_desc - line_remarks - oem_partno - status - } - status - user_email - } -} diff --git a/client/templates/parts_order_confirmation/parts_order_confirmation.template.html b/client/templates/parts_order_confirmation/parts_order_confirmation.template.html deleted file mode 100644 index c17866942..000000000 --- a/client/templates/parts_order_confirmation/parts_order_confirmation.template.html +++ /dev/null @@ -1,122 +0,0 @@ -
    -

    - Deliver By: {{parts_orders_by_pk.deliver_by}} -

    - - - - - - - - - - - - - - - - - - - - - -
    - Line Description - - Part # - - Price - - Line Remarks -
    - {{#each parts_orders_by_pk.parts_order_lines}} -
    - {{this.line_desc}} - - {{this.oem_partno}} - - ${{this.act_price}} - - {{this.line_remarks}} -
    {{/each}}
    -

    Order Placed by {{parts_orders_by_pk.user_email}}.

    -
    diff --git a/client/templates/payment_receipt/payment_receipt.query.gql b/client/templates/payment_receipt/payment_receipt.query.gql deleted file mode 100644 index 6cdf0f71e..000000000 --- a/client/templates/payment_receipt/payment_receipt.query.gql +++ /dev/null @@ -1,26 +0,0 @@ -query REPORT_PAYMENT_RECEIPT($id: uuid!) { - payments_by_pk(id: $id) { - job { - id - vehicle { - id - v_model_desc - v_make_desc - v_model_yr - v_vin - } - ro_number - est_number - clm_no - clm_total - ded_amt - } - id - amount - memo - transactionid - stripeid - payer - type - } -} diff --git a/client/templates/payment_receipt/payment_receipt.template.html b/client/templates/payment_receipt/payment_receipt.template.html deleted file mode 100644 index 381dc9a3c..000000000 --- a/client/templates/payment_receipt/payment_receipt.template.html +++ /dev/null @@ -1,10 +0,0 @@ -
    -

    RECEIPT OF PAYMENT

    -

    Amount: {{payments_by_pk.amount}}

    -

    Memo: {{payments_by_pk.memo}}

    -

    RO Number: {{payments_by_pk.job.ro_number}} / {{payments_by_pk.job.est_number}}

    -

    Payer: {{payments_by_pk.payer}}

    -

    StripeID: {{payments_by_pk.stripeid}}

    -

    Amount: {{payments_by_pk.amount}}

    -

     

    -
    \ No newline at end of file diff --git a/client/templates/time_tickets_by_employee/time_tickets_by_employee.graphql b/client/templates/time_tickets_by_employee/time_tickets_by_employee.graphql deleted file mode 100644 index 9776e3fa3..000000000 --- a/client/templates/time_tickets_by_employee/time_tickets_by_employee.graphql +++ /dev/null @@ -1,25 +0,0 @@ -query REPORT_TIME_TICKETS_IN_RANGE($id: uuid!, $start: date!, $end: date!) { - employees_by_pk(id: $id) { - id - first_name - last_name - employee_number - timetickets(where: { date: { _gte: $start, _lte: $end } }) { - actualhrs - ciecacode - clockoff - clockon - cost_center - created_at - date - id - rate - productivehrs - memo - job { - id - ro_number - } - } - } -} diff --git a/client/templates/time_tickets_by_employee/time_tickets_by_employee.html b/client/templates/time_tickets_by_employee/time_tickets_by_employee.html deleted file mode 100644 index f032ae5e1..000000000 --- a/client/templates/time_tickets_by_employee/time_tickets_by_employee.html +++ /dev/null @@ -1,55 +0,0 @@ -
    -

    Employee Time Tickets

    - - - - - - - - -
    Employee: {{employees_by_pk.first_name}} {{employees_by_pk.last_name}}  -

     

    -
    -

    Time Tickets

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    DateCost CenterActual HrsProductive HrsShift Clock OnShift Clock OffShift Time
    {{#each employees_by_pk.timetickets}}      
    {{this.date}}{{this.cost_center}}{{this.actualhrs}}{{this.productivehrs}}{{moment this.clockon format="MM/DD/YYYY @ hh:mm:ss"}}{{moment this.clockoff format="MM/DD/YYYY @ hh:mm:ss"}}{{moment this.clockoff diff=this.clockon }}
    {{/each}}      
    -
    \ No newline at end of file diff --git a/hasura/migrations/1609980609388_alter_table_public_bodyshops_add_column_imexshopid/down.yaml b/hasura/migrations/1609980609388_alter_table_public_bodyshops_add_column_imexshopid/down.yaml new file mode 100644 index 000000000..e0d91252c --- /dev/null +++ b/hasura/migrations/1609980609388_alter_table_public_bodyshops_add_column_imexshopid/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."bodyshops" DROP COLUMN "imexshopid"; + type: run_sql diff --git a/hasura/migrations/1609980609388_alter_table_public_bodyshops_add_column_imexshopid/up.yaml b/hasura/migrations/1609980609388_alter_table_public_bodyshops_add_column_imexshopid/up.yaml new file mode 100644 index 000000000..cf4791447 --- /dev/null +++ b/hasura/migrations/1609980609388_alter_table_public_bodyshops_add_column_imexshopid/up.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."bodyshops" ADD COLUMN "imexshopid" text NULL UNIQUE; + type: run_sql diff --git a/hasura/migrations/1609980625366_update_permission_user_public_table_bodyshops/down.yaml b/hasura/migrations/1609980625366_update_permission_user_public_table_bodyshops/down.yaml new file mode 100644 index 000000000..b595b5e10 --- /dev/null +++ b/hasura/migrations/1609980625366_update_permission_user_public_table_bodyshops/down.yaml @@ -0,0 +1,74 @@ +- 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 + - city + - country + - created_at + - deliverchecklist + - email + - enforce_class + - federal_tax_id + - id + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - logo_img_path + - md_categories + - md_classes + - md_ins_cos + - md_labor_rates + - md_messaging_presets + - md_notes_presets + - md_order_statuses + - md_parts_locations + - 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 + - target_touchtime + - template_header + - textid + - updated_at + - zip_post + computed_fields: [] + filter: + associations: + bodyshop: + associations: + user: + authid: + _eq: X-Hasura-User-Id + role: user + table: + name: bodyshops + schema: public + type: create_select_permission diff --git a/hasura/migrations/1609980625366_update_permission_user_public_table_bodyshops/up.yaml b/hasura/migrations/1609980625366_update_permission_user_public_table_bodyshops/up.yaml new file mode 100644 index 000000000..0acc18430 --- /dev/null +++ b/hasura/migrations/1609980625366_update_permission_user_public_table_bodyshops/up.yaml @@ -0,0 +1,75 @@ +- 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 + - city + - country + - created_at + - deliverchecklist + - email + - enforce_class + - federal_tax_id + - id + - imexshopid + - inhousevendorid + - insurance_vendor_id + - intakechecklist + - logo_img_path + - md_categories + - md_classes + - md_ins_cos + - md_labor_rates + - md_messaging_presets + - md_notes_presets + - md_order_statuses + - md_parts_locations + - 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 + - target_touchtime + - template_header + - textid + - updated_at + - zip_post + computed_fields: [] + filter: + associations: + bodyshop: + associations: + user: + authid: + _eq: X-Hasura-User-Id + role: user + table: + name: bodyshops + schema: public + type: create_select_permission diff --git a/hasura/migrations/metadata.yaml b/hasura/migrations/metadata.yaml index 474e5af9b..d2ca5432a 100644 --- a/hasura/migrations/metadata.yaml +++ b/hasura/migrations/metadata.yaml @@ -713,6 +713,7 @@ tables: - enforce_class - federal_tax_id - id + - imexshopid - inhousevendorid - insurance_vendor_id - intakechecklist diff --git a/sendemail.js b/sendemail.js index 5f3c81e0b..559af7c6f 100644 --- a/sendemail.js +++ b/sendemail.js @@ -6,16 +6,24 @@ require("dotenv").config({ ), }); +const inlineCssTool = require("inline-css"); + const mailjet = require("node-mailjet").connect( process.env.email_api, process.env.email_secret ); -exports.sendEmail = (req, res) => { +exports.sendEmail = async (req, res) => { if (process.env.NODE_ENV !== "production") { console.log("[EMAIL] Incoming Message", req.body.from.name); } + // const inlinedCssHtml = await inlineCssTool(req.body.html, { + // url: "https://imex.online", + // }); + + // console.log("inlinedCssHtml", inlinedCssHtml); + const request = mailjet.post("send", { version: "v3.1" }).request({ Messages: [ { @@ -36,13 +44,6 @@ exports.sendEmail = (req, res) => { // "Dear passenger 1, welcome to Mailjet! May the delivery force be with you!", HTMLPart: req.body.html, Attachments: req.body.attachments || null, - // Attachments: [ - // { - // ContentType: "text/plain", - // Filename: "test.txt", - // Base64Content: "VGhpcyBpcyB5b3VyIGF0dGFjaGVkIGZpbGUhISEK", - // }, - // ], }, ], }); diff --git a/server/render/inlinecss.js b/server/render/inlinecss.js index c3b59fbad..543590638 100644 --- a/server/render/inlinecss.js +++ b/server/render/inlinecss.js @@ -19,5 +19,8 @@ exports.inlinecss = (req, res) => { .then((inlinedHtml) => { res.send(inlinedHtml); }) - .catch((error) => res.send(error)); + .catch((error) => { + console.log("Error while inlining CSS", JSON.stringify(error)); + res.send(error); + }); };