488 lines
17 KiB
JavaScript
488 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 = import.meta.env.VITE_APP_REPORTS_SERVER_URL;
|
|
|
|
jsreport.serverUrl = server;
|
|
|
|
let Templates;
|
|
export function GenerateTemplates(){
|
|
//Required as a part of the transition to Vite.
|
|
//Previous method had the template hash generating before translations loaded, resulting in empty files.
|
|
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;
|
|
}
|