Files
bodyshop/client/src/utils/RenderTemplate.js
2024-02-22 18:44:43 -05:00

483 lines
17 KiB
JavaScript

import {gql} from "@apollo/client";
import jsreport from "@jsreport/browser-client";
import {notification} from "antd";
import axios from "axios";
import _ from "lodash";
import {auth} from "../firebase/firebase.utils";
import {setEmailOptions} from "../redux/email/email.actions";
import {store} from "../redux/store";
import client from "../utils/GraphQLClient";
import cleanAxios from "./CleanAxios";
import {TemplateList} from "./TemplateConstants";
import {generateTemplate} from "./graphQLmodifier";
const server = process.env.REACT_APP_REPORTS_SERVER_URL;
jsreport.serverUrl = server;
const Templates = TemplateList();
export default async function RenderTemplate(
templateObject,
bodyshop,
renderAsHtml = false,
renderAsExcel = false,
renderAsText = false
) {
if (window.jsr3) {
jsreport.serverUrl = "https://reports3.test.imex.online/";
}
const jsrAuth = (await axios.post("/utils/jsr")).data;
jsreport.headers["Authorization"] = jsrAuth;
//Query assets that match the template name. Must be in format <<templateName>>.query
let {contextData, useShopSpecificTemplate} = await fetchContextData(
templateObject,
jsrAuth
);
const {ignoreCustomMargins} = Templates[templateObject.name];
let reportRequest = {
template: {
name: useShopSpecificTemplate
? `/${bodyshop.imexshopid}/${templateObject.name}`
: `/${templateObject.name}`,
...(renderAsHtml
? {}
: {
recipe: "chrome-pdf",
...(!ignoreCustomMargins && {
chrome: {
marginTop:
bodyshop.logo_img_path &&
bodyshop.logo_img_path.headerMargin &&
bodyshop.logo_img_path.headerMargin > 36
? bodyshop.logo_img_path.headerMargin
: "36px",
marginBottom:
bodyshop.logo_img_path &&
bodyshop.logo_img_path.footerMargin &&
bodyshop.logo_img_path.footerMargin > 50
? bodyshop.logo_img_path.footerMargin
: "50px",
},
}),
}),
...(renderAsExcel ? {recipe: "html-to-xlsx"} : {}),
...(renderAsText ? {recipe: "text"} : {}),
},
data: {
...contextData,
...templateObject.variables,
...templateObject.context,
headerpath: `/${bodyshop.imexshopid}/header.html`,
footerpath: `/${bodyshop.imexshopid}/footer.html`,
bodyshop: bodyshop,
filters: templateObject?.filters,
sorters: templateObject?.sorters,
offset: bodyshop.timezone, //dayjs().utcOffset(),
defaultSorters: templateObject?.defaultSorters,
},
};
try {
const render = await jsreport.render(reportRequest);
if (!renderAsHtml) {
render.download(
(Templates[templateObject.name] &&
Templates[templateObject.name].title) ||
""
);
} else {
let pdf;
if (bodyshop.attach_pdf_to_email) {
const pdfRequest = _.cloneDeep(reportRequest); //Updates to spread in the header details.
pdfRequest.template = {
...pdfRequest.template,
...{
recipe: "chrome-pdf",
...(!ignoreCustomMargins && {
chrome: {
marginTop:
bodyshop.logo_img_path &&
bodyshop.logo_img_path.headerMargin &&
bodyshop.logo_img_path.headerMargin > 36
? bodyshop.logo_img_path.headerMargin
: "36px",
marginBottom:
bodyshop.logo_img_path &&
bodyshop.logo_img_path.footerMargin &&
bodyshop.logo_img_path.footerMargin > 50
? bodyshop.logo_img_path.footerMargin
: "50px",
},
}),
},
};
const pdfRender = await jsreport.render(pdfRequest);
pdf = await pdfRender.toDataURI();
}
const html = await render.toString();
return new Promise((resolve, reject) => {
resolve({
pdf,
filename:
Templates[templateObject.name] &&
Templates[templateObject.name].title,
html,
});
});
}
} catch (error) {
notification["error"]({message: JSON.stringify(error)});
}
}
export async function RenderTemplates(
templateObjects,
bodyshop,
renderAsHtml = false
) {
//Query assets that match the template name. Must be in format <<templateName>>.query
let unsortedTemplatesAndData = [];
let proms = [];
const jsrAuth = (await axios.post("/utils/jsr")).data;
jsreport.headers["Authorization"] = jsrAuth;
templateObjects.forEach((template) => {
proms.push(
(async () => {
let {contextData, useShopSpecificTemplate} = await fetchContextData(
template,
jsrAuth
);
unsortedTemplatesAndData.push({
templateObject: template,
contextData,
useShopSpecificTemplate,
});
})()
);
});
await Promise.all(proms);
//Re-order list to follow speedprint.
// var templateAndData = _.sortBy(unsortedTemplatesAndData, function (item) {
// return templateObjects.findIndex(
// (template) => template.name === item.templateObject.name
// );
// });
if (window.jsr3) {
jsreport.serverUrl = "https://reports3.test.imex.online/";
}
unsortedTemplatesAndData.sort(function (a, b) {
return (
templateObjects.findIndex((x) => x.name === a.templateObject.name) -
templateObjects.findIndex((x) => x.name === b.templateObject.name)
);
});
const templateAndData = unsortedTemplatesAndData;
let rootTemplate = templateAndData.shift();
let reportRequest = {
template: {
name: rootTemplate.useShopSpecificTemplate
? `/${bodyshop.imexshopid}/${rootTemplate.templateObject.name}`
: `/${rootTemplate.templateObject.name}`,
...(renderAsHtml
? {}
: {
recipe: "chrome-pdf",
chrome: {
marginTop:
bodyshop.logo_img_path &&
bodyshop.logo_img_path.headerMargin &&
bodyshop.logo_img_path.headerMargin > 36
? bodyshop.logo_img_path.headerMargin
: "36px",
marginBottom:
bodyshop.logo_img_path &&
bodyshop.logo_img_path.footerMargin &&
bodyshop.logo_img_path.footerMargin > 50
? bodyshop.logo_img_path.footerMargin
: "50px",
},
}),
pdfOperations: [
{
template: {
name: "/components/Header-Footer",
recipe: "chrome-pdf",
engine: "handlebars",
},
type: "merge",
},
...templateAndData.map((template) => {
return {
template: {
chrome: {
marginTop:
bodyshop.logo_img_path &&
bodyshop.logo_img_path.headerMargin &&
bodyshop.logo_img_path.headerMargin > 36
? bodyshop.logo_img_path.headerMargin
: "36px",
marginBottom:
bodyshop.logo_img_path &&
bodyshop.logo_img_path.footerMargin &&
bodyshop.logo_img_path.footerMargin > 50
? bodyshop.logo_img_path.footerMargin
: "50px",
},
name: template.useShopSpecificTemplate
? `/${bodyshop.imexshopid}/${template.templateObject.name}`
: `/${template.templateObject.name}`,
...(renderAsHtml ? {} : {recipe: "chrome-pdf"}),
},
type: "append",
// mergeWholeDocument: true,
// renderForEveryPage: true,
};
}),
],
},
data: {
...extend(
rootTemplate.contextData,
...templateAndData.map((temp) => temp.contextData)
),
// ...rootTemplate.templateObject.variables,
// ...rootTemplate.templateObject.context,
headerpath: `/${bodyshop.imexshopid}/header.html`,
footerpath: `/${bodyshop.imexshopid}/footer.html`,
bodyshop: bodyshop,
offset: bodyshop.timezone,
},
};
try {
const render = await jsreport.render(reportRequest);
if (!renderAsHtml) {
render.download("Speed Print");
} else {
return render.toString();
}
} catch (error) {
notification["error"]({message: JSON.stringify(error)});
}
}
export const GenerateDocument = async (
template,
messageOptions,
sendType,
jobid
) => {
const bodyshop = store.getState().user.bodyshop;
if (sendType === "e") {
store.dispatch(
setEmailOptions({
jobid,
messageOptions: {
...messageOptions,
to: Array.isArray(messageOptions.to)
? messageOptions.to
: [messageOptions.to],
},
template,
})
);
} else if (sendType === "x") {
await RenderTemplate(template, bodyshop, false, true);
} else if (sendType === "text") {
await RenderTemplate(template, bodyshop, false, false, true);
} else {
await RenderTemplate(template, bodyshop);
}
};
export const GenerateDocuments = async (templates) => {
const bodyshop = store.getState().user.bodyshop;
await RenderTemplates(templates, bodyshop);
};
export const fetchFilterData = async ({name}) => {
try {
const bodyshop = store.getState().user.bodyshop;
const jsrAuth = (await axios.post("/utils/jsr")).data;
jsreport.headers["FirebaseAuthorization"] =
"Bearer " + (await auth.currentUser.getIdToken());
const folders = await cleanAxios.get(`${server}/odata/folders`, {
headers: {Authorization: jsrAuth},
});
const shopSpecificFolder = folders.data.value.find(
(f) => f.name === bodyshop.imexshopid
);
const jsReportFilters = await cleanAxios.get(
`${server}/odata/assets?$filter=name eq '${name}.filters'`,
{headers: {Authorization: jsrAuth}}
);
console.log("🚀 ~ fetchFilterData ~ jsReportFilters:", jsReportFilters);
let parsedFilterData;
let useShopSpecificTemplate = false;
// let shopSpecificTemplate;
if (shopSpecificFolder) {
let shopSpecificTemplate = jsReportFilters.data.value.find(
(f) => f?.folder?.shortid === shopSpecificFolder.shortid
);
if (shopSpecificTemplate) {
useShopSpecificTemplate = true;
parsedFilterData = atob(shopSpecificTemplate.content);
}
}
if (!parsedFilterData) {
const generalTemplate = jsReportFilters.data.value.find((f) => !f.folder);
useShopSpecificTemplate = false;
if (generalTemplate) parsedFilterData = atob(generalTemplate.content);
}
const data = JSON.parse(parsedFilterData);
return {
data,
useShopSpecificTemplate,
success: true,
}
} catch {
return {
success: false,
}
}
};
const fetchContextData = async (templateObject, jsrAuth) => {
const bodyshop = store.getState().user.bodyshop;
jsreport.headers["FirebaseAuthorization"] =
"Bearer " + (await auth.currentUser.getIdToken());
const folders = await cleanAxios.get(`${server}/odata/folders`, {
headers: {Authorization: jsrAuth},
});
const shopSpecificFolder = folders.data.value.find(
(f) => f.name === bodyshop.imexshopid
);
const jsReportQueries = await cleanAxios.get(
`${server}/odata/assets?$filter=name eq '${templateObject.name}.query'`,
{headers: {Authorization: jsrAuth}}
);
let templateQueryToExecute;
let useShopSpecificTemplate = false;
// let shopSpecificTemplate;
if (shopSpecificFolder) {
let shopSpecificTemplate = jsReportQueries.data.value.find(
(f) => f?.folder?.shortid === shopSpecificFolder.shortid
);
if (shopSpecificTemplate) {
useShopSpecificTemplate = true;
templateQueryToExecute = atob(shopSpecificTemplate.content);
}
}
if (!templateQueryToExecute) {
const generalTemplate = jsReportQueries.data.value.find((f) => !f.folder);
useShopSpecificTemplate = false;
templateQueryToExecute = atob(generalTemplate.content);
}
// Commented out for future revision debugging
// console.log('Template Object');
// console.dir(templateObject);
// console.log('Unmodified Query');
// console.dir(templateQueryToExecute);
const hasFilters = templateObject?.filters?.length > 0;
const hasSorters = templateObject?.sorters?.length > 0;
const hasDefaultSorters = templateObject?.defaultSorters?.length > 0;
// We have no template filters or sorters, so we can just execute the query and return the data
if (!hasFilters && !hasSorters && !hasDefaultSorters) {
let contextData = {};
if (templateQueryToExecute) {
const {data} = await client.query({
query: gql(templateQueryToExecute),
variables: {...templateObject.variables},
});
contextData = data;
}
return {contextData, useShopSpecificTemplate};
}
return await generateTemplate(
templateQueryToExecute,
templateObject,
useShopSpecificTemplate
);
};
//export const displayTemplateInWindow = (html) => {
// try {
// var newWin = window.open("", "_blank", "toolbar=0,location=0,menubar=0");
// newWin.document.write(html);
// setTimeout(function () {
// newWin.document.close();
// newWin.focus();
// newWin.print();
// newWin.close();
// }, 500);
// } catch (error) {
// console.log("Unable to write to new window.", error);
// }
// };
// export const displayTemplateInWindowNoprint = (html) => {
// try {
// var newWin = window.open("", "_blank", "toolbar=0,location=0,menubar=0");
// newWin.document.write(html);
// setTimeout(function () {
// newWin.document.close();
// newWin.focus();
// //newWin.print();
// //newWin.close();
// }, 500);
// } catch (error) {
// console.log("Unable to write to new window.", error);
// }
// };
function extend(o1, o2, o3) {
var result = {},
obj;
for (var i = 0; i < arguments.length; i++) {
obj = arguments[i];
for (var key in obj) {
if (Object.prototype.toString.call(obj[key]) === "[object Object]") {
if (typeof result[key] === "undefined") {
result[key] = {};
}
result[key] = extend(result[key], obj[key]);
} else {
result[key] = obj[key];
}
}
}
return result;
}