Modified render styles to improve printability

This commit is contained in:
Patrick Fic
2020-09-10 15:55:25 -07:00
parent a0bb07abfd
commit 984c001bd8
15 changed files with 187 additions and 92 deletions

View File

@@ -15213,6 +15213,27 @@
<folder_node>
<name>labels</name>
<children>
<concept_node>
<name>additionaltotal</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>allocations</name>
<definition_loaded>false</definition_loaded>

BIN
client/public/kavia.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,9 +1,37 @@
/* body {
body {
font-family: "Open Sans", sans-serif;
line-height: 1.25;
/* padding: 10mm 10mm 10mm 10mm !important; */
}
@page {
size: auto; /* auto is the initial value */
/* this affects the margin in the printer settings */
margin: 25mm 25mm 25mm 25mm;
color: tomato;
}
/* Unknown whether the below actually gets embedded */
/* @media print {
@page {
size: Letter;
margin: 0;
}
html,
body {
width: 210mm;
height: 282mm;
font-size: 11px;
background: #fff;
overflow: visible;
}
body {
padding-top: 15mm;
}
} */
table {
table.imex-table {
border: 1px solid #ccc;
border-collapse: collapse;
margin: 0;
@@ -12,74 +40,25 @@ table {
table-layout: fixed;
}
table caption {
table.imex-table caption {
font-size: 1.5em;
margin: 0.5em 0 0.75em;
}
table tr {
table.imex-table tr {
background-color: #f8f8f8;
border: 1px solid #ddd;
padding: 0.35em;
padding: 0.1rem;
}
table th,
table td {
padding: 0.625em;
table.imex-table th,
table.imex-table td {
padding: 0.3rem;
text-align: center;
}
table th {
table.imex-table th {
font-size: 0.85em;
letter-spacing: 0.1em;
text-transform: uppercase;
}
@media screen and (max-width: 600px) {
table {
border: 0;
}
table caption {
font-size: 1.3em;
}
table thead {
border: none;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
table tr {
border-bottom: 3px solid #ddd;
display: block;
margin-bottom: 0.625em;
}
table td {
border-bottom: 1px solid #ddd;
display: block;
font-size: 0.8em;
text-align: right;
}
table td::before {
/*
* aria-label has no advantage, it won't be read inside a table
content: attr(aria-label);
*/
content: attr(data-label);
float: left;
font-weight: bold;
text-transform: uppercase;
}
table td:last-child {
border-bottom: 0;
}
}

View File

@@ -1,5 +1,7 @@
import { Col, Result, Row, Statistic, Typography } from "antd";
import Dinero from "dinero.js";
import { JsonEditor as Editor } from "jsoneditor-react";
import "jsoneditor-react/es/editor.min.css";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -218,7 +220,7 @@ export function JobsTotalsTableComponent({ bodyshop, job }) {
<tr>
<td>{t("jobs.labels.additionaltotal")}</td>
<td className="currency">
{Dinero(job.job_totals.parts.additional).toFormat()}
{Dinero(job.job_totals.additional).toFormat()}
</td>
<td></td>
</tr>
@@ -293,6 +295,9 @@ export function JobsTotalsTableComponent({ bodyshop, job }) {
/>
</div>
<JobCalculateTotals job={job} />
<Editor
value={{ CIECA: job.cieca_ttl.data, ImEXCalc: job.job_totals }}
/>
</div>
</Col>
</Row>

View File

@@ -20,6 +20,7 @@ export default function ShopTemplateSaveButton({
emailEditorRef.current.exportHtml(async (data) => {
inlineCss(data.html, {
url: `${window.location.protocol}://${window.location.host}/`,
preserveMediaQueries: true,
}).then(async function (inlineHtml) {
const result = await updateTemplate({
variables: {

View File

@@ -1,28 +1,16 @@
import "codemirror/addon/hint/show-hint";
import "codemirror/addon/lint/lint";
import "codemirror-graphql/hint";
import "codemirror-graphql/lint";
import "codemirror-graphql/mode";
import "codemirror/addon/hint/show-hint";
import "codemirror/addon/lint/lint";
import "codemirror/lib/codemirror.css";
import "codemirror/theme/material.css";
import "codemirror/addon/hint/show-hint";
import React, { useEffect, useRef, useState } from "react";
import { Controlled as CmEditor } from "react-codemirror2";
import EmailEditor from "react-email-editor";
import GqlSchema from "../../graphql/schema";
import ShopTemplateEditorSaveButton from "../shop-template-editor-save-button/shop-template-editor-save-button.component";
import ShopTemplateTestRender from "../shop-template-test-render/shop-template-test-render.component";
// CodeMirror.fromTextArea(document.getElementById("gqlcm"), {
// mode: "graphql",
// lint: {
// // schema: myGraphQLSchema,
// },
// hintOptions: {
// // schema: myGraphQLSchema,
// },
// });
export default function ShopTemplateEditorComponent({
templateId,
@@ -58,7 +46,7 @@ export default function ShopTemplateEditorComponent({
<EmailEditor
style={{ width: "100%" }}
ref={emailEditorRef}
minHeight="800px"
minHeight="700px"
onLoad={() => setEditorLoaded(true)}
options={{
// customCSS: [
@@ -75,9 +63,9 @@ export default function ShopTemplateEditorComponent({
],
}}
/>
<div style={{ display: "flex" }}>
<div style={{ display: "flex", width: "90vw" }}>
<CmEditor
style={{ width: "30rem" }}
style={{ flex: 1 }}
value={editorContent.gql}
options={{
mode: "graphql",
@@ -94,6 +82,7 @@ export default function ShopTemplateEditorComponent({
}}
/>
<ShopTemplateTestRender
style={{ flex: 1 }}
query={editorContent.gql}
emailEditorRef={emailEditorRef}
/>

View File

@@ -19,7 +19,12 @@ const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function ShopTemplateTestRender({ bodyshop, query, emailEditorRef }) {
export function ShopTemplateTestRender({
bodyshop,
query,
emailEditorRef,
style,
}) {
const [variables, setVariables] = useState({ id: "uuid" });
const [loading, setLoading] = useState(false);
const { t } = useTranslation();
@@ -31,6 +36,7 @@ export function ShopTemplateTestRender({ bodyshop, query, emailEditorRef }) {
emailEditorRef.current.exportHtml(async (data) => {
inlineCss(data.html, {
url: `${window.location.protocol}://${window.location.host}/`,
removeLinkTags: false,
}).then(async function (inlineHtml) {
try {
const { data: contextData } = await client.query({
@@ -59,13 +65,11 @@ export function ShopTemplateTestRender({ bodyshop, query, emailEditorRef }) {
};
return (
<div>
<div style={{ width: "20rem" }}>
<Editor value={variables} onChange={(e) => setVariables(e)} />
<Button loading={loading} type="ghost" onClick={handleTestRender}>
{t("bodyshop.actions.testrender")}
</Button>
</div>
<div style={style}>
<Editor value={variables} onChange={(e) => setVariables(e)} />
<Button loading={loading} type="ghost" onClick={handleTestRender}>
{t("bodyshop.actions.testrender")}
</Button>
</div>
);
}

View File

@@ -64,6 +64,7 @@ export default function ShopTemplatesListContainer({ visibleState }) {
<div style={{ display: "flex", flexDirection: "column" }}>
<div>{TemplateList[item.name].title}</div>
<div>{TemplateList[item.name].description}</div>
<div>{TemplateList[item.name].drivingid}</div>
</div>
</Skeleton>
</List.Item>

View File

@@ -942,6 +942,7 @@
"scheddates": "Schedule Dates"
},
"labels": {
"additionaltotal": "Additional Total",
"allocations": "Allocations",
"appointmentconfirmation": "Send confirmation to customer?",
"audit": "Audit Trail",

View File

@@ -942,6 +942,7 @@
"scheddates": ""
},
"labels": {
"additionaltotal": "",
"allocations": "",
"appointmentconfirmation": "¿Enviar confirmación al cliente?",
"audit": "",

View File

@@ -942,6 +942,7 @@
"scheddates": ""
},
"labels": {
"additionaltotal": "",
"allocations": "",
"appointmentconfirmation": "Envoyer une confirmation au client?",
"audit": "",

View File

@@ -4,6 +4,14 @@ export const EmailSettings = {
};
export const TemplateList = {
//Verified Completed items
estimate_detail: {
title: "Estimate Detail",
description: "Est Detail",
drivingId: "job",
key: "estimate_detail",
},
//Non Completed Items
appointment_reminder: {
title: "Appointment Reminder",
description: "Sent to a customer as a reminder of an upcoming appointment.",
@@ -23,12 +31,7 @@ export const TemplateList = {
drivingId: "partsorder",
key: "parts_order_confirmation",
},
estimate_detail: {
title: "Estimate Detail Lines",
description: "Est Detail",
drivingId: "job",
key: "estimate_detail",
},
cover_sheet_landscape: {
title: "Cover Sheet - Landscape",
description: "Cover sheet landscape",

View File

View File

@@ -41,7 +41,6 @@ function CalculateAdditional(job) {
jl.lbr_op === "OP15"
)
.reduce((acc, val) => {
console.log("val", val);
return acc.add(
Dinero({ amount: Math.round((val.act_price || 0) * 100) })
);

View File

@@ -8,12 +8,25 @@ require("dotenv").config({
});
var _ = require("lodash");
const Handlebars = require("handlebars");
const phone = require("phone");
var Dinero = require("dinero.js");
Dinero.defaultCurrency = "CAD";
Dinero.globalLocale = "en-CA";
//Usage: {{moment appointments_by_pk.start format="dddd, DD MMMM YYYY"}}
Handlebars.registerHelper("round", function (context, block) {
if (context && context.hash) {
block = _.cloneDeep(context);
context = undefined;
}
try {
return context.toFixed(2);
} catch {
return context;
}
});
Handlebars.registerHelper("dinerof", function (context, block) {
if (context && context.hash) {
block = _.cloneDeep(context);
@@ -26,6 +39,77 @@ Handlebars.registerHelper("dinerof", function (context, block) {
return "";
});
Handlebars.registerHelper("phonef", function (context, block) {
if (context && context.hash) {
block = _.cloneDeep(context);
context = undefined;
}
var ph = phone(context)[0];
if (context) {
return ph;
}
return "";
});
Handlebars.registerHelper("partType", function (context, block) {
if (!context) return "";
switch (context.toUpperCase()) {
case "PAA":
return "Aftermarket";
case "PAE":
return "Existing";
case "PAN":
return "OEM";
case "PAO":
return "Other";
case "PAS":
return "Sublet";
case "PASL":
return "Sublet";
case "PAL":
return "LKQ";
case "PAM":
return "Remanufactured";
case "PAC":
return "Chrome";
case "PAP":
return "OEM Partial";
case "PAR":
return "Record";
default:
return context;
}
});
Handlebars.registerHelper("lbrType", function (context, block) {
if (!context) return "";
switch (context.toUpperCase()) {
case "LAA":
return "Aluminum";
case "LAB":
return "Body";
case "LAD":
return "Diagnostic";
case "LAF":
return "Frame";
case "LAG":
return "Glass";
case "LAM":
return "Mechanical";
case "LAR":
return "Refinish";
case "LAS":
return "Structural";
case "LAU":
return "Detail";
default:
return context;
}
});
Handlebars.registerHelper("objectKeys", function (obj, block) {
var accum = "";
@@ -41,7 +125,10 @@ Handlebars.registerHelper("dinero", function (context, block) {
block = _.cloneDeep(context);
context = undefined;
}
var amount = Dinero({ amount: Math.round((context || 0) * 100) });
var amount = Dinero({
amount: Math.round((context || 0) * 100),
currency: "CAD",
});
return amount.toFormat();
});
@@ -50,6 +137,9 @@ Handlebars.registerHelper("moment", function (context, block) {
block = _.cloneDeep(context);
context = undefined;
}
if (!!!context) return "";
var date = moment(context);
if (block.hash.timezone) {