mirror of
https://github.com/frappe/books.git
synced 2024-12-22 19:09:01 +00:00
incr: move pdf printer to main
- fix pdf printing
This commit is contained in:
parent
4810396434
commit
0951e11cb1
@ -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
56
main/saveHtmlAsPdf.ts
Normal 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;
|
||||
}
|
@ -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": [
|
||||
|
@ -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 = {
|
||||
|
@ -1,13 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Print</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="printTarget"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1 +0,0 @@
|
||||
import './styles/index.css';
|
@ -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;
|
||||
}
|
@ -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);
|
||||
showExportInFolder(t`Save as PDF Successful`, 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) {
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user