import { gql } from "@apollo/client"; import { notification } from "antd"; import axios from "axios"; import jsreport from "jsreport-browser-client-dist"; import moment from "moment"; import { auth } from "../firebase/firebase.utils"; import { setEmailOptions } from "../redux/email/email.actions"; import { store } from "../redux/store"; import client from "../utils/GraphQLClient"; import { TemplateList } from "./TemplateConstants"; const server = process.env.REACT_APP_REPORTS_SERVER_URL; jsreport.serverUrl = server; const Templates = TemplateList(); export default async function RenderTemplate( templateObject, bodyshop, renderAsHtml = false ) { //Query assets that match the template name. Must be in format <>.query let { contextData, useShopSpecificTemplate } = await fetchContextData( templateObject ); let reportRequest = { template: { name: useShopSpecificTemplate ? `/${bodyshop.imexshopid}/${templateObject.name}` : `/${templateObject.name}`, ...(renderAsHtml ? {} : { recipe: "chrome-pdf" }), }, data: { ...contextData, ...templateObject.variables, ...templateObject.context, headerpath: `/${bodyshop.imexshopid}/header.html`, bodyshop: bodyshop, offset: moment().utcOffset(), }, }; try { const render = await jsreport.renderAsync(reportRequest); if (!renderAsHtml) { render.download(Templates[templateObject.name].title || ""); } else { return new Promise((resolve, reject) => { resolve(render.toString()); }); } } 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 <>.query let templateAndData = []; let proms = []; templateObjects.forEach((template) => { proms.push( (async () => { let { contextData, useShopSpecificTemplate } = await fetchContextData( template ); templateAndData.push({ templateObject: template, contextData, useShopSpecificTemplate, }); })() ); }); await Promise.all(proms); let rootTemplate = templateAndData.shift(); let reportRequest = { template: { name: rootTemplate.useShopSpecificTemplate ? `/${bodyshop.imexshopid}/${rootTemplate.templateObject.name}` : `/${rootTemplate.templateObject.name}`, ...(renderAsHtml ? {} : { recipe: "chrome-pdf" }), pdfOperations: templateAndData.map((template) => { return { template: { 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`, bodyshop: bodyshop, }, }; console.log("reportRequest", reportRequest); try { const render = await jsreport.renderAsync(reportRequest); if (!renderAsHtml) { render.download("Speed Print"); } else { return new Promise((resolve, reject) => { resolve(render.toString()); }); } } catch (error) { notification["error"]({ message: JSON.stringify(error) }); } } export const GenerateDocument = async (template, messageOptions, sendType) => { const bodyshop = store.getState().user.bodyshop; if (sendType === "e") { store.dispatch( setEmailOptions({ messageOptions, template, }) ); } else { await RenderTemplate(template, bodyshop); } }; export const GenerateDocuments = async (templates) => { const bodyshop = store.getState().user.bodyshop; await RenderTemplates(templates, bodyshop); }; const fetchContextData = async (templateObject) => { console.log("Fetching context data", templateObject); jsreport.headers["Authorization"] = "Bearer " + (await auth.currentUser.getIdToken()); const jsReportQueries = await axios.get( `${server}/odata/assets?$filter=name eq '${templateObject.name}.query'` ); 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 { //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." ); } let contextData = {}; if (templateQueryToExecute) { const { data } = await client.query({ query: gql(templateQueryToExecute), variables: { ...templateObject.variables }, fetchPolicy: "network-only", }); contextData = data; } return { contextData, 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; }