2
0
mirror of https://github.com/frappe/books.git synced 2024-11-08 14:50:56 +00:00

incr: move pdf printer to main

- fix pdf printing
This commit is contained in:
18alantom 2022-05-19 17:38:46 +05:30
parent 4810396434
commit 0951e11cb1
9 changed files with 99 additions and 90 deletions

View File

@ -4,12 +4,12 @@ import fs from 'fs/promises';
import path from 'path';
import databaseManager from '../backend/database/manager';
import { Main } from '../main';
import saveHtmlAsPdf from '../src/saveHtmlAsPdf';
import { DatabaseMethod } from '../utils/db/types';
import { DatabaseResponse } from '../utils/ipc/types';
import { IPC_ACTIONS } from '../utils/messages';
import { getUrlAndTokenString, sendError } from './contactMothership';
import { getLanguageMap } from './getLanguageMap';
import { saveHtmlAsPdf } from './saveHtmlAsPdf';
export default function registerIpcMainActionListeners(main: Main) {
ipcMain.handle(IPC_ACTIONS.TOGGLE_MAXIMIZE_CURRENT_WINDOW, (event) => {
@ -46,7 +46,7 @@ export default function registerIpcMainActionListeners(main: Main) {
ipcMain.handle(
IPC_ACTIONS.SAVE_HTML_AS_PDF,
async (event, html, savePath) => {
return await saveHtmlAsPdf(html, savePath);
return await saveHtmlAsPdf(html, savePath, app);
}
);

56
main/saveHtmlAsPdf.ts Normal file
View File

@ -0,0 +1,56 @@
import { App, BrowserWindow } from 'electron';
import fs from 'fs/promises';
import path from 'path';
const PRINT_OPTIONS = {
marginsType: 1, // no margin
pageSize: 'A4',
printBackground: true,
printBackgrounds: true,
printSelectionOnly: false,
};
export async function saveHtmlAsPdf(
html: string,
savePath: string,
app: App
): Promise<boolean> {
/**
* Store received html as a file in a tempdir,
* this will be loaded into the print view
*/
const tempRoot = app.getPath('temp');
const filename = path.parse(savePath).name;
const htmlPath = path.join(tempRoot, `${filename}.html`);
await fs.writeFile(htmlPath, html, { encoding: 'utf-8' });
const printWindow = getInitializedPrintWindow(htmlPath);
/**
* After the printWindow content is ready, save as pdf and
* then close the window and delete the temp html file.
*/
return await new Promise((resolve) => {
printWindow.webContents.once('did-finish-load', () => {
printWindow.webContents.printToPDF(PRINT_OPTIONS).then((data) => {
fs.writeFile(savePath, data).then(() => {
printWindow.close();
fs.unlink(htmlPath).then(() => {
resolve(true);
});
});
});
});
});
}
function getInitializedPrintWindow(printFilePath: string) {
const printWindow = new BrowserWindow({
width: 595,
height: 842,
show: false,
});
printWindow.loadFile(printFilePath);
return printWindow;
}

View File

@ -115,23 +115,19 @@
"fieldtype": "Select",
"options": [
{
"value": "Inter",
"label": "Inter"
"value": "Arial",
"label": "Arial"
},
{
"value": "Times New Roman",
"label": "Times New Roman"
},
{
"value": "Arial",
"label": "Arial"
},
{
"value": "Courier",
"label": "Courier"
}
],
"default": "Inter"
"default": "Arial"
}
],
"quickEditFields": [

View File

@ -56,6 +56,7 @@ import Button from 'src/components/Button.vue';
import PageHeader from 'src/components/PageHeader.vue';
import InvoiceTemplate from 'src/components/SalesInvoice/InvoiceTemplate.vue';
import TwoColumnForm from 'src/components/TwoColumnForm.vue';
import { fyo } from 'src/initFyo';
import { makePDF } from 'src/utils/ipcCalls';
import { IPC_ACTIONS } from 'utils/messages';
@ -77,6 +78,10 @@ export default {
async mounted() {
this.doc = await fyo.doc.getDoc(this.schemaName, this.name);
this.printSettings = await fyo.doc.getSingle('PrintSettings');
if (fyo.store.isDevelopment) {
window.pv = this;
}
},
computed: {
printTemplate() {
@ -84,13 +89,33 @@ export default {
},
},
methods: {
constructPrintDocument() {
const html = document.createElement('html');
const head = document.createElement('head');
const body = document.createElement('body');
const style = document.getElementsByTagName('style');
const styleTags = Array.from(style)
.map((s) => s.outerHTML)
.join('\n');
head.innerHTML = [
'<meta charset="UTF-8">',
'<title>Print Window</title>',
styleTags,
].join('\n');
body.innerHTML = this.$refs.printContainer.innerHTML;
html.append(head, body);
return html.outerHTML;
},
async makePDF() {
const savePath = await this.getSavePath();
if (!savePath) return;
const html = this.$refs.printContainer.innerHTML;
fyo.telemetry.log(Verb.Exported, 'SalesInvoice', { extension: 'pdf' });
const html = this.constructPrintDocument()
await makePDF(html, savePath);
fyo.telemetry.log(Verb.Exported, 'SalesInvoice', { extension: 'pdf' });
},
async getSavePath() {
const options = {

View File

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Print</title>
</head>
<body>
<div class="printTarget"></div>
</body>
</html>

View File

@ -1 +0,0 @@
import './styles/index.css';

View File

@ -1,59 +0,0 @@
import { BrowserWindow } from 'electron';
import fs from 'fs/promises';
import { sleep } from 'utils';
const PRINT_OPTIONS = {
marginsType: 1, // no margin
pageSize: 'A4',
printBackground: true,
printBackgrounds: true,
printSelectionOnly: false,
};
export default async function saveHtmlAsPdf(
html: string,
savePath: string
): Promise<void> {
const printWindow = getInitializedPrintWindow();
printWindow.webContents.executeJavaScript(`
document.body.innerHTML = \`${html}\`;
`);
return await new Promise((resolve) => {
printWindow.webContents.on('did-finish-load', async () => {
await sleep(1); // Required else pdf'll be blank.
const data = await printWindow.webContents.printToPDF(PRINT_OPTIONS);
await fs.writeFile(savePath, data);
resolve();
});
});
}
function getInitializedPrintWindow() {
const printWindow = new BrowserWindow({
width: 595,
height: 842,
show: false,
webPreferences: {
contextIsolation: false,
nodeIntegration: false,
},
});
const printWindowUrl = getPrintWindowUrl();
printWindow.loadURL(printWindowUrl);
return printWindow;
}
function getPrintWindowUrl() {
// @ts-ignore
let url = global.WEBPACK_DEV_SERVER_URL as string | undefined;
if (url) {
url = url + 'print';
} else {
url = 'app://./print.html';
}
return url;
}

View File

@ -26,8 +26,17 @@ export async function showItemInFolder(filePath: string) {
}
export async function makePDF(html: string, savePath: string) {
await ipcRenderer.invoke(IPC_ACTIONS.SAVE_HTML_AS_PDF, html, savePath);
const success = await ipcRenderer.invoke(
IPC_ACTIONS.SAVE_HTML_AS_PDF,
html,
savePath
);
if (success) {
showExportInFolder(t`Save as PDF Successful`, savePath);
} else {
showToast({ message: t`Export Failed`, type: 'error' });
}
}
export async function runWindowAction(name: WindowAction) {

View File

@ -32,10 +32,6 @@ module.exports = {
entry: 'src/renderer.ts',
filename: 'index.html',
},
print: {
entry: 'src/print.ts',
filename: 'print.html',
},
},
runtimeCompiler: true,
lintOnSave: process.env.NODE_ENV !== 'production',