/** * Provides functions and properties to export pdf * * @module pdf-export */ declare const window: any; interface IExportParams { addSumRow: boolean dateAndPlace: boolean extraParams: object imgLocation: string orientation: string signature: boolean statusInfo: boolean template: IRecord type: string } import { createPdf } from 'pdfmake/build/pdfmake'; import moment from 'moment'; import { IRecord } from '../interfaces/record'; import { assert } from '@ember/debug'; /** * Creates pdf from elements (note: call this function preferably through export service) * @function createPdfFromElements * @param {any} this * @param {any} elements * @param {String} mode * @param {String} headers * @param {Number} headerSize * @param {IExportParams} exportParams */ /* istanbul ignore next */ export async function createPdfFromElements(self: any, elements: any, mode = 'download', headers = '', headerSize = 8, exportParams: IExportParams) { if (!self.Collector) assert('Collector service injection missing') if (!self.session) assert('Session service injection missing') if (!self.intl) assert('Intl service injection missing') if (!self.cordova) assert('Cordova service injection missing') const pdfContent = [] let orientation = exportParams.orientation ? exportParams.orientation : 'portrait' const additionalHeaders = await getHeaders(headers, headerSize, self.Collector, self.session) pdfContent.push(additionalHeaders) elements = putElementsInColumns(elements) for (const element of elements) { if (!element) return; if (element.table && !exportParams.orientation) { if (element.table.body[0].length > 7) { orientation = 'landscape' } } pdfContent.push(element) } let pageSize: any = 'A4' if (exportParams.signature) { pdfContent.push({ style: 'marginTop', table: { widths: ['auto', 140, 30, 'auto', 140], body: [ [ { border: [false, true, false, false], text: self.intl.t('report.worktask.signature') + ':', }, { border: [false, true, false, false], text: '', }, { border: [false, false, false, false], text: '', }, { border: [false, true, false, false], text: self.intl.t('thereport.print_name') + ':', }, { border: [false, true, false, false], text: '', }, ], ], }, }) } if (exportParams.dateAndPlace) { pdfContent.push({ style: 'marginTop', table: { widths: ['auto', 140, 55, 'auto', 140], body: [ [ { border: [false, true, false, false], text: self.intl.t('thereport.date') + ':', }, { border: [false, true, false, false], text: '', }, { border: [false, false, false, false], text: '', }, { border: [false, true, false, false], text: self.intl.t('thereport.place') + ':', }, { border: [false, true, false, false], text: '', }, ], ], }, }) } if (elements[0].table && (exportParams.imgLocation && exportParams.imgLocation === 'afterReport')) { pdfContent.push(tryToExtractImages(elements[0].table.body, orientation)) } const docDefinition: any = { content: pdfContent, pageOrientation: orientation, footer(currentPage: any, pageCount: any) { return getFooter(currentPage, pageCount) }, pageMargins: [15, 15, 15, 15], styles: { tableHeader: { bold: true }, bigText: { bold: true, fontSize: 20 }, table: { fontSize: 10 }, footer: { fontSize: 8, color: 'grey' }, headertext: { fontSize: 8 }, marginTop: { margin: [0, 40, 0, 0] }, }, } const pdfDocGenerator = createPdf(docDefinition); pdfDocGenerator.getStream(); for (const item of pdfContent) { if (item.style === 'table' && item._maxWidth > 842 && orientation !== 'portrait') { pageSize = {height: item._maxWidth, width: item._maxWidth / Math.sqrt(2)} continue } } docDefinition.pageSize = pageSize if (mode === 'download') { if (window.cordova) { pdfDocGenerator.getBuffer(async (buffer: any) => { const utf8 = new Uint8Array(buffer); const binaryArray = utf8.buffer; return await self.cordova.saveFile(binaryArray, 'export', 'pdf') }) } else { return pdfDocGenerator.download('export.pdf') } } else if (mode === 'base64') { return new Promise((resolve, reject) => { pdfDocGenerator.getBase64((file: string) => { if (file) resolve(file) else (reject()) }) }) } } /* istanbul ignore next */ function putElementsInColumns(elements: any) { const ret: any[] = [] let row: any[] = [] const cell: any[] = [] let fillingColumn = null for (const element of elements) { if (!element.column) { row = [] ret.push(element) } else { if (!element.width) element.width = '*' cell.push(element) fillingColumn = element.column } } if (fillingColumn) { row.push(cell) ret.push({columns: row}) } return ret } /* istanbul ignore next */ async function getHeaders(additionalheaders: string, headerSize: number, collector: any, session: any) { const logo = await collector.getLogo() const company = session.currentUser.company return { columns: [ [ { fit: [120, 40], image: logo, margin: [0, 0, 0, 20], }, { text: additionalheaders, style: 'headertext', fontSize: headerSize, }, ], { width: '*', text: company || '', alignment: 'right', fontSize: 22, margin: [0, 0, 0, 20], }, ], } } /* istanbul ignore next */ function tryToExtractImages(data: any, orientation: string) { const maxHeight = orientation === 'landscape' ? 570 : 830 const maxWidth = orientation === 'landscape' ? 830 : 570 const allImages = [] for (const element of data) { for (const el of element) { if (el.image) allImages.push({image: el.image, maxHeight, maxWidth}) } } return allImages } /* istanbul ignore next */ function getFooter(currentPage: number, pageCount: number) { return { columns: [ {text: 'movenium.com', style: 'footer', margin: [ 20, 2, 0, 0 ]}, {text: moment().format('L') + ' ' + currentPage.toString() + '/' + pageCount, style: 'footer', margin: [ 0, 2, 20, 0 ], alignment: 'right' }, ], } }