mirror of
https://github.com/frappe/books.git
synced 2024-12-26 12:28:12 +00:00
-Use puppeteer core for smaller app size
This commit is contained in:
parent
4cbb99ed2d
commit
d352e39082
@ -51,9 +51,9 @@
|
|||||||
"octicons": "^7.2.0",
|
"octicons": "^7.2.0",
|
||||||
"passport": "^0.4.0",
|
"passport": "^0.4.0",
|
||||||
"passport-jwt": "^4.0.0",
|
"passport-jwt": "^4.0.0",
|
||||||
"puppeteer": "^1.2.0",
|
"puppeteer-core": "^1.19.0",
|
||||||
"sass-loader": "^7.0.3",
|
"sass-loader": "^7.0.3",
|
||||||
"sharp": "^0.22.1",
|
"sharp": "^0.23.0",
|
||||||
"showdown": "^1.8.6",
|
"showdown": "^1.8.6",
|
||||||
"socket.io": "^2.0.4",
|
"socket.io": "^2.0.4",
|
||||||
"sqlite3": "^4.0.9",
|
"sqlite3": "^4.0.9",
|
||||||
|
126
server/pdf.js
126
server/pdf.js
@ -1,5 +1,5 @@
|
|||||||
const frappe = require('frappejs');
|
const frappe = require('frappejs');
|
||||||
const puppeteer = require('puppeteer');
|
const puppeteer = require('puppeteer-core');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { getTmpDir } = require('frappejs/server/utils');
|
const { getTmpDir } = require('frappejs/server/utils');
|
||||||
@ -7,87 +7,97 @@ const { getHTML } = require('frappejs/common/print');
|
|||||||
const { getRandomString } = require('frappejs/utils');
|
const { getRandomString } = require('frappejs/utils');
|
||||||
|
|
||||||
async function makePDF(html, filepath) {
|
async function makePDF(html, filepath) {
|
||||||
const browser = await puppeteer.launch();
|
const browser = await puppeteer.launch();
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
await page.setContent(html);
|
await page.setContent(html);
|
||||||
await page.addStyleTag({
|
await page.addStyleTag({
|
||||||
url: 'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css'
|
url:
|
||||||
})
|
'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css'
|
||||||
await page.pdf({
|
});
|
||||||
path: filepath,
|
await page.pdf({
|
||||||
format: 'A4'
|
path: filepath,
|
||||||
});
|
format: 'A4'
|
||||||
await browser.close();
|
});
|
||||||
|
await browser.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getPDFForElectron(doctype, name, destination, htmlContent) {
|
async function getPDFForElectron(doctype, name, destination, htmlContent) {
|
||||||
const { remote, shell } = require('electron');
|
const { remote, shell } = require('electron');
|
||||||
const { BrowserWindow } = remote;
|
const { BrowserWindow } = remote;
|
||||||
const html = htmlContent || await getHTML(doctype, name);
|
const html = htmlContent || (await getHTML(doctype, name));
|
||||||
const filepath = path.join(destination, name + '.pdf');
|
const filepath = path.join(destination, name + '.pdf');
|
||||||
|
|
||||||
const fs = require('fs')
|
const fs = require('fs');
|
||||||
let printWindow = new BrowserWindow({
|
let printWindow = new BrowserWindow({
|
||||||
width: 600,
|
width: 600,
|
||||||
height: 800,
|
height: 800,
|
||||||
show: false
|
show: false
|
||||||
})
|
});
|
||||||
printWindow.loadURL(`file://${path.join(__static, 'print.html')}`);
|
printWindow.loadURL(`file://${path.join(__static, 'print.html')}`);
|
||||||
|
|
||||||
printWindow.on('closed', () => {
|
printWindow.on('closed', () => {
|
||||||
printWindow = null;
|
printWindow = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
const code = `
|
const code = `
|
||||||
document.body.innerHTML = \`${html}\`;
|
document.body.innerHTML = \`${html}\`;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
printWindow.webContents.executeJavaScript(code);
|
printWindow.webContents.executeJavaScript(code);
|
||||||
|
|
||||||
const printPromise = new Promise(resolve => {
|
const printPromise = new Promise(resolve => {
|
||||||
printWindow.webContents.on('did-finish-load', () => {
|
printWindow.webContents.on('did-finish-load', () => {
|
||||||
printWindow.webContents.printToPDF({
|
printWindow.webContents.printToPDF(
|
||||||
|
{
|
||||||
marginsType: 1, // no margin
|
marginsType: 1, // no margin
|
||||||
pageSize: 'A4',
|
pageSize: 'A4',
|
||||||
printBackground: true
|
printBackground: true
|
||||||
}, (error, data) => {
|
},
|
||||||
if (error) throw error
|
(error, data) => {
|
||||||
|
if (error) throw error;
|
||||||
printWindow.close();
|
printWindow.close();
|
||||||
fs.writeFile(filepath, data, (error) => {
|
fs.writeFile(filepath, data, error => {
|
||||||
if (error) throw error
|
if (error) throw error;
|
||||||
resolve(shell.openItem(filepath));
|
resolve(shell.openItem(filepath));
|
||||||
})
|
});
|
||||||
})
|
}
|
||||||
})
|
);
|
||||||
})
|
});
|
||||||
|
});
|
||||||
|
|
||||||
await printPromise;
|
await printPromise;
|
||||||
// await makePDF(html, filepath);
|
// await makePDF(html, filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupExpressRoute() {
|
function setupExpressRoute() {
|
||||||
if (!frappe.app) return;
|
if (!frappe.app) return;
|
||||||
frappe.app.post('/api/method/pdf', frappe.asyncHandler(handlePDFRequest));
|
frappe.app.post('/api/method/pdf', frappe.asyncHandler(handlePDFRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handlePDFRequest(req, res) {
|
async function handlePDFRequest(req, res) {
|
||||||
const args = req.body;
|
const args = req.body;
|
||||||
const { doctype, name } = args;
|
const { doctype, name } = args;
|
||||||
const html = await getHTML(doctype, name);
|
const html = await getHTML(doctype, name);
|
||||||
|
|
||||||
const filepath = path.join(getTmpDir(), `frappe-pdf-${getRandomString()}.pdf`);
|
const filepath = path.join(
|
||||||
await makePDF(html, filepath);
|
getTmpDir(),
|
||||||
|
`frappe-pdf-${getRandomString()}.pdf`
|
||||||
|
);
|
||||||
|
await makePDF(html, filepath);
|
||||||
|
|
||||||
const file = fs.createReadStream(filepath);
|
const file = fs.createReadStream(filepath);
|
||||||
const stat = fs.statSync(filepath);
|
const stat = fs.statSync(filepath);
|
||||||
res.setHeader('Content-Length', stat.size);
|
res.setHeader('Content-Length', stat.size);
|
||||||
res.setHeader('Content-Type', 'application/pdf');
|
res.setHeader('Content-Type', 'application/pdf');
|
||||||
res.setHeader('Content-Disposition', `attachment; filename=${path.basename(filepath)}`);
|
res.setHeader(
|
||||||
file.pipe(res);
|
'Content-Disposition',
|
||||||
|
`attachment; filename=${path.basename(filepath)}`
|
||||||
|
);
|
||||||
|
file.pipe(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
makePDF,
|
makePDF,
|
||||||
setupExpressRoute,
|
setupExpressRoute,
|
||||||
getPDFForElectron
|
getPDFForElectron
|
||||||
}
|
};
|
||||||
|
@ -73,7 +73,7 @@ export default {
|
|||||||
this.doc.set('name', '');
|
this.doc.set('name', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.defaults) {
|
if (this.doc.isNew() && this.defaults) {
|
||||||
for (let fieldname in this.defaults) {
|
for (let fieldname in this.defaults) {
|
||||||
const value = this.defaults[fieldname];
|
const value = this.defaults[fieldname];
|
||||||
await this.doc.set(fieldname, value);
|
await this.doc.set(fieldname, value);
|
||||||
@ -123,13 +123,23 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
this.doc.set('submitted', 1);
|
await this.doc.set('submitted', 1);
|
||||||
await this.save();
|
try {
|
||||||
|
await this.save();
|
||||||
|
} catch (e) {
|
||||||
|
await this.doc.set('submitted', 0);
|
||||||
|
await this.doc.set('_dirty', false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async revert() {
|
async revert() {
|
||||||
this.doc.set('submitted', 0);
|
await this.doc.set('submitted', 0);
|
||||||
await this.save();
|
try {
|
||||||
|
await this.save();
|
||||||
|
} catch (e) {
|
||||||
|
await this.doc.set('submitted', 1);
|
||||||
|
await this.doc.set('_dirty', false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
print() {
|
print() {
|
||||||
|
@ -75,6 +75,19 @@ export default {
|
|||||||
: true;
|
: true;
|
||||||
|
|
||||||
this.disableSave = this.doc.isNew() ? false : !this.isDirty;
|
this.disableSave = this.doc.isNew() ? false : !this.isDirty;
|
||||||
|
},
|
||||||
|
getFormTitle() {
|
||||||
|
const _ = this._;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return _(
|
||||||
|
this.meta.getFormTitle(this.doc) ||
|
||||||
|
this.meta.label ||
|
||||||
|
this.doc.doctype
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
return _(this.meta.label || this.doc.doctype);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -85,7 +98,7 @@ export default {
|
|||||||
const _ = this._;
|
const _ = this._;
|
||||||
|
|
||||||
if (this.doc.isNew()) {
|
if (this.doc.isNew()) {
|
||||||
return _('New {0}', _(this.meta.label || this.doc.doctype));
|
return _('New {0}', this.getFormTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
const titleField = this.meta.titleField || 'name';
|
const titleField = this.meta.titleField || 'name';
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
:docfield="getDocField(fieldname)"
|
:docfield="getDocField(fieldname)"
|
||||||
:value="$data[fieldname]"
|
:value="$data[fieldname]"
|
||||||
:doc="doc"
|
:doc="doc"
|
||||||
:autofocus="doc.isNew() && (i === currentSection || i === 0) && j === 0 && k === 0"
|
:autofocus="doc.isNew() && (i === currentSection || i === 0) && j === 0 && k === 0 && !$data[fieldname]"
|
||||||
@change="value => updateDoc(fieldname, value)"
|
@change="value => updateDoc(fieldname, value)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import Float from './Float';
|
import Float from './Float';
|
||||||
export default {
|
export default {
|
||||||
extends: Float
|
extends: Float,
|
||||||
}
|
methods: {
|
||||||
|
parse(value) {
|
||||||
|
return frappe.format(value, 'Currency');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
Reference in New Issue
Block a user