2
0
mirror of https://github.com/frappe/books.git synced 2025-01-11 10:38:14 +00:00

Merge pull request #220 from 18alantom/fix-reported-issues-and-improvements

fix: reported issues and improvements
This commit is contained in:
Alan 2021-10-19 14:47:37 +05:30 committed by GitHub
commit c8732d6d8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 238 additions and 228 deletions

View File

@ -97,8 +97,23 @@ module.exports = {
return doc.getFrom('Address', doc.address, 'addressDisplay'); return doc.getFrom('Address', doc.address, 'addressDisplay');
} }
} }
},
{
fieldname: 'gstin',
label: 'GSTIN No.',
fieldtype: 'Data',
hidden: form => {
return form.gstType === 'Registered Regular' ? 0 : 1;
}
} }
], ],
quickEditFields: ['email', 'phone', 'address', 'defaultAccount', 'currency'] quickEditFields: [
'email',
'phone',
'address',
'defaultAccount',
'currency',
'gstin'
]
}; };

View File

@ -102,7 +102,7 @@ module.exports = {
label: 'Amount', label: 'Amount',
fieldtype: 'Currency', fieldtype: 'Currency',
required: 1, required: 1,
default: doc => doc.getSum('for', 'amount') formula: doc => doc.getSum('for', 'amount')
}, },
{ {
fieldname: 'writeoff', fieldname: 'writeoff',

View File

@ -19,6 +19,9 @@ export default {
computed: { computed: {
partyField() { partyField() {
return this.doc.doctype === 'SalesInvoice' ? 'customer' : 'supplier'; return this.doc.doctype === 'SalesInvoice' ? 'customer' : 'supplier';
},
isSalesInvoice() {
return this.doc.doctype === 'SalesInvoice';
} }
} }
}; };

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="border h-full"> <div class="border h-full">
<div> <div>
<div class="px-6 pt-6" v-if="printSettings && accountingSettings"> <div class="px-6 pt-6" v-if="printSettings">
<div class="flex text-sm text-gray-900 border-b pb-4"> <div class="flex text-sm text-gray-900 border-b pb-4">
<div class="w-1/3"> <div class="w-1/3">
<div v-if="printSettings.displayLogo"> <div v-if="printSettings.displayLogo">
@ -11,7 +11,7 @@
/> />
</div> </div>
<div class="text-xl text-gray-700 font-semibold" v-else> <div class="text-xl text-gray-700 font-semibold" v-else>
{{ accountingSettings.companyName }} {{ frappe.AccountingSettings.companyName }}
</div> </div>
</div> </div>
<div class="w-1/3"> <div class="w-1/3">
@ -19,7 +19,10 @@
<div class="mt-1">{{ printSettings.phone }}</div> <div class="mt-1">{{ printSettings.phone }}</div>
</div> </div>
<div class="w-1/3"> <div class="w-1/3">
<div v-if="address">{{ address.addressDisplay }}</div> <div v-if="companyAddress">{{ companyAddress.addressDisplay }}</div>
<div v-if="printSettings && printSettings.gstin">
GSTIN: {{ printSettings.gstin }}
</div>
</div> </div>
</div> </div>
</div> </div>
@ -33,60 +36,62 @@
{{ frappe.format(doc.date, 'Date') }} {{ frappe.format(doc.date, 'Date') }}
</div> </div>
</div> </div>
<div class="w-1/3"> <div class="w-1/3" v-if="party">
<div class="py-1 text-right text-lg font-semibold"> <div class="py-1 text-right text-lg font-semibold">
{{ doc[partyField.fieldname] }} {{ party.name }}
</div>
<div v-if="partyDoc" class="mt-1 text-xs text-gray-600 text-right">
{{ partyDoc.addressDisplay }}
</div> </div>
<div <div
v-if="partyDoc && partyDoc.gstin" v-if="party && party.addressDisplay"
class="mt-1 text-xs text-gray-600 text-right" class="mt-1 text-xs text-gray-600 text-right"
> >
GSTIN: {{ partyDoc.gstin }} {{ party.addressDisplay }}
</div>
<div
v-if="party && party.gstin"
class="mt-1 text-xs text-gray-600 text-right"
>
GSTIN: {{ party.gstin }}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="mt-2 px-6 text-base"> <div class="mt-2 px-6 text-base">
<div> <div>
<Row class="text-gray-600 w-full" :ratio="ratio"> <div class="text-gray-600 w-full flex border-b">
<div class="py-4"> <div class="py-4 w-5/12">Item</div>
{{ _('No') }} <div class="py-4 text-right w-1/12">Quantity</div>
<div class="py-4 text-right w-3/12">Rate</div>
<div class="py-4 text-right w-3/12">Amount</div>
</div> </div>
<div <div
class="py-4" class="flex py-1 text-gray-900 w-full border-b"
v-for="df in itemFields"
:key="df.fieldname"
:class="textAlign(df)"
>
{{ df.label }}
</div>
</Row>
<Row
class="text-gray-900 w-full"
v-for="row in doc.items" v-for="row in doc.items"
:key="row.name" :key="row.name"
:ratio="ratio"
> >
<div class="py-4"> <div class="w-5/12 py-4">{{ row.item }}</div>
{{ row.idx + 1 }} <div class="w-1/12 text-right py-4">
{{ format(row, 'quantity') }}
</div>
<div class="w-3/12 text-right py-4">{{ format(row, 'rate') }}</div>
<div class="w-3/12 text-right py-4">
{{ format(row, 'amount') }}
</div> </div>
<div
class="py-4"
v-for="df in itemFields"
:key="df.fieldname"
:class="textAlign(df)"
>
{{ frappe.format(row[df.fieldname], df) }}
</div> </div>
</Row>
</div> </div>
</div> </div>
</div> </div>
<div class="px-6 mt-2 flex justify-end text-base"> <div class="px-6 mt-2 flex justify-end text-base">
<div class="w-64"> <div class="w-1/2 bg-pink">
<div
class="uppercase text-sm tracking-widest font-semibold text-gray-800 mt-2"
>
Notes
</div>
<div class="my-4 text-lg whitespace-pre-line">
{{ doc.terms }}
</div>
</div>
<div class="w-1/2">
<div class="flex pl-2 justify-between py-3 border-b"> <div class="flex pl-2 justify-between py-3 border-b">
<div>{{ _('Subtotal') }}</div> <div>{{ _('Subtotal') }}</div>
<div>{{ frappe.format(doc.netTotal, 'Currency') }}</div> <div>{{ frappe.format(doc.netTotal, 'Currency') }}</div>
@ -111,57 +116,11 @@
</template> </template>
<script> <script>
import frappe from 'frappejs'; import Base from './Base';
import Row from '@/components/Row';
export default { export default {
name: 'Default', name: 'Default',
props: ['doc', 'printSettings'], extends: Base,
components: { props: ['doc', 'printSettings']
Row
},
data() {
return {
accountingSettings: null
};
},
computed: {
meta() {
return this.doc && this.doc.meta;
},
address() {
return this.printSettings && this.printSettings.getLink('address');
},
partyDoc() {
return this.doc.getLink(this.partyField.fieldname);
},
partyField() {
let fieldname = {
SalesInvoice: 'customer',
PurchaseInvoice: 'supplier'
}[this.doc.doctype];
return this.meta.getField(fieldname);
},
itemFields() {
let itemsMeta = frappe.getMeta(`${this.doc.doctype}Item`);
return ['item', 'quantity', 'rate', 'amount'].map(fieldname =>
itemsMeta.getField(fieldname)
);
},
ratio() {
return [0.3].concat(this.itemFields.map(() => 1));
}
},
methods: {
textAlign(df) {
return ['Currency', 'Int', 'Float'].includes(df.fieldtype)
? 'text-right'
: '';
}
},
async mounted() {
this.accountingSettings = await frappe.getSingle('AccountingSettings');
await this.doc.loadLink(this.partyField.fieldname);
}
}; };
</script> </script>

View File

@ -23,12 +23,18 @@
<div class="text-sm text-gray-800" v-if="companyAddress"> <div class="text-sm text-gray-800" v-if="companyAddress">
{{ companyAddress.addressDisplay }} {{ companyAddress.addressDisplay }}
</div> </div>
<div
class="text-sm text-gray-800"
v-if="printSettings && printSettings.gstin"
>
GSTIN: {{ printSettings.gstin }}
</div>
</div> </div>
</div> </div>
<div class="mt-8 text-lg"> <div class="mt-8 text-lg">
<div class="flex"> <div class="flex">
<div class="w-1/3 font-semibold"> <div class="w-1/3 font-semibold">
{{ doc.doctype === 'SalesInvoice' ? 'Invoice' : 'Bill' }} {{ isSalesInvoice ? 'Invoice' : 'Bill' }}
</div> </div>
<div class="w-2/3 text-gray-800"> <div class="w-2/3 text-gray-800">
<div class="font-semibold"> <div class="font-semibold">
@ -41,7 +47,7 @@
</div> </div>
<div class="mt-4 flex"> <div class="mt-4 flex">
<div class="w-1/3 font-semibold"> <div class="w-1/3 font-semibold">
{{ doc.doctype === 'SalesInvoice' ? 'Customer' : 'Supplier' }} {{ isSalesInvoice ? 'Customer' : 'Supplier' }}
</div> </div>
<div class="w-2/3 text-gray-800" v-if="party"> <div class="w-2/3 text-gray-800" v-if="party">
<div class="font-semibold"> <div class="font-semibold">
@ -50,6 +56,7 @@
<div> <div>
{{ party.addressDisplay }} {{ party.addressDisplay }}
</div> </div>
<div v-if="party && party.gstin">GSTIN: {{ party.gstin }}</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -42,22 +42,34 @@
<div <div
class="uppercase text-sm font-semibold tracking-widest text-gray-800" class="uppercase text-sm font-semibold tracking-widest text-gray-800"
> >
To {{ isSalesInvoice ? 'To' : 'From' }}
</div> </div>
<div class="mt-4 text-black leading-relaxed text-lg"> <div class="mt-4 text-black leading-relaxed text-lg">
{{ party.name }} <br /> {{ party.name }} <br />
{{ party.addressDisplay }} {{ party.addressDisplay }}
</div> </div>
<div
class="mt-4 text-black leading-relaxed text-lg"
v-if="party && party.gstin"
>
GSTIN: {{ party.gstin }}
</div>
</div> </div>
<div class="w-1/2" v-if="companyAddress"> <div class="w-1/2" v-if="companyAddress">
<div <div
class="uppercase text-sm font-semibold tracking-widest text-gray-800" class="uppercase text-sm font-semibold tracking-widest text-gray-800 ml-8"
> >
From {{ isSalesInvoice ? 'From' : 'To' }}
</div> </div>
<div class="mt-4 text-black leading-relaxed text-lg"> <div class="mt-4 ml-8 text-black leading-relaxed text-lg">
{{ companyAddress.addressDisplay }} {{ companyAddress.addressDisplay }}
</div> </div>
<div
class="mt-4 ml-8 text-black leading-relaxed text-lg"
v-if="printSettings && printSettings.gstin"
>
GSTIN: {{ printSettings.gstin }}
</div>
</div> </div>
</div> </div>
<div class="px-12 py-10 border-b"> <div class="px-12 py-10 border-b">

View File

@ -25,14 +25,15 @@ module.exports = {
label: 'Description', label: 'Description',
fieldtype: 'Text', fieldtype: 'Text',
formula: (row, doc) => doc.getFrom('Item', row.item, 'description'), formula: (row, doc) => doc.getFrom('Item', row.item, 'description'),
hidden: 1 hidden: 1,
formulaDependsOn: ['item']
}, },
{ {
fieldname: 'quantity', fieldname: 'quantity',
label: 'Quantity', label: 'Quantity',
fieldtype: 'Float', fieldtype: 'Float',
required: 1, required: 1,
formula: () => 1 formula: row => row.quantity || 1
}, },
{ {
fieldname: 'rate', fieldname: 'rate',
@ -43,7 +44,8 @@ module.exports = {
let baseRate = await doc.getFrom('Item', row.item, 'rate'); let baseRate = await doc.getFrom('Item', row.item, 'rate');
return baseRate / doc.exchangeRate; return baseRate / doc.exchangeRate;
}, },
getCurrency: (row, doc) => doc.currency getCurrency: (row, doc) => doc.currency,
formulaDependsOn: ['item']
}, },
{ {
fieldname: 'baseRate', fieldname: 'baseRate',
@ -66,10 +68,8 @@ module.exports = {
label: 'Tax', label: 'Tax',
fieldtype: 'Link', fieldtype: 'Link',
target: 'Tax', target: 'Tax',
formula: (row, doc) => { formula: (row, doc) => doc.getFrom('Item', row.item, 'tax'),
if (row.tax) return row.tax; formulaDependsOn: ['item']
return doc.getFrom('Item', row.item, 'tax');
}
}, },
{ {
fieldname: 'amount', fieldname: 'amount',

View File

@ -54,23 +54,18 @@ export default {
}; };
}, },
methods: { methods: {
openFileSelector() { async openFileSelector() {
remote.dialog.showOpenDialog( const options = {
remote.getCurrentWindow(),
{
title: frappe._('Select Image'), title: frappe._('Select Image'),
properties: ['openFile'], properties: ['openFile'],
filters: [ filters: [{ name: 'Image', extensions: ['png', 'jpg', 'jpeg', 'webp'] }]
{ name: 'Image', extensions: ['png', 'jpg', 'jpeg', 'webp'] } };
]
}, const { filePaths } = await remote.dialog.showOpenDialog(options);
async files => { if (filePaths && filePaths[0]) {
if (files && files[0]) { let dataURL = await this.getDataURL(filePaths[0]);
let dataURL = await this.getDataURL(files[0]);
this.triggerChange(dataURL); this.triggerChange(dataURL);
} }
}
);
}, },
getDataURL(filePath) { getDataURL(filePath) {
let fs = require('fs'); let fs = require('fs');

View File

@ -9,7 +9,6 @@
:class="['resize-none', inputClasses]" :class="['resize-none', inputClasses]"
:value="value" :value="value"
:placeholder="inputPlaceholder" :placeholder="inputPlaceholder"
:readonly="isReadOnly"
@blur="e => triggerChange(e.target.value)" @blur="e => triggerChange(e.target.value)"
@focus="e => $emit('focus', e)" @focus="e => $emit('focus', e)"
@input="e => $emit('input', e)" @input="e => $emit('input', e)"

View File

@ -199,6 +199,13 @@ export default {
}, },
toValue(date) { toValue(date) {
// toISOString is buggy and reduces the day by one
// this is because it considers the UTC timestamp
// in order to circumvent that we need to use luxon/moment
// but that refactor could take some time, so fixing the time difference
// as suggested in this answer.
// https://stackoverflow.com/a/16084846/3541205
date.setHours(0, -date.getTimezoneOffset(), 0, 0);
return date.toISOString().slice(0, 10); return date.toISOString().slice(0, 10);
}, },

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="py-4 px-8 flex justify-between window-drag"> <div class="my-4 mx-4 flex justify-between window-drag">
<div class="window-no-drag"> <div class="window-no-drag">
<slot name="title" /> <slot name="title" />
</div> </div>

View File

@ -63,6 +63,10 @@ import router from './router';
console.error(err, vm, info); console.error(err, vm, info);
}; };
process.on('unhandledRejection', error => {
console.error(error);
});
/* eslint-disable no-new */ /* eslint-disable no-new */
new Vue({ new Vue({
el: '#app', el: '#app',

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="mt-6"> <div class="w-96 mx-auto mt-4">
<template v-if="hasData"> <template v-if="hasData">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="font-medium">{{ _('Cashflow') }}</div> <div class="font-medium">{{ _('Cashflow') }}</div>
@ -21,7 +21,7 @@
v-else v-else
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 889 240" viewBox="0 0 889 240"
class="w-full h-full" class="w-10/12 h-5/6 ml-4 mr-4 my-2"
> >
<defs> <defs>
<linearGradient x1="50%" y1="100%" x2="50%" y2=".889%" id="a"> <linearGradient x1="50%" y1="100%" x2="50%" y2=".889%" id="a">

View File

@ -6,17 +6,17 @@
<SearchBar class="ml-2" /> <SearchBar class="ml-2" />
</template> </template>
</PageHeader> </PageHeader>
<div class="px-8"> <div class="mx-4">
<div class="border-t" /> <div class="border-t" />
<Cashflow /> <Cashflow />
<div class="my-10 border-t" /> <div class="my-4 mt-0 border-t" />
<UnpaidInvoices /> <UnpaidInvoices />
<div class="my-10 border-t" /> <div class="my-4 border-t" />
<div class="flex -mx-4"> <div class="w-96 flex mx-auto">
<div class="w-1/2 px-4"> <div class="w-1/2 mx-4">
<ProfitAndLoss /> <ProfitAndLoss />
</div> </div>
<div class="w-1/2 px-4"> <div class="w-1/2 mx-4">
<Expenses /> <Expenses />
</div> </div>
</div> </div>

View File

@ -30,7 +30,7 @@
<div <div
v-if="hasData" v-if="hasData"
class="absolute text-base text-center font-semibold" class="absolute text-base text-center font-semibold"
style="right: 3.8rem; top: 32%;" style="right: 6rem; top: 32%;"
> >
<div> <div>
{{ frappe.format(totalExpense, 'Currency') }} {{ frappe.format(totalExpense, 'Currency') }}

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="flex -mx-4"> <div class="w-96 flex justify-between mx-auto">
<div <div
class="w-1/2 px-4 flex flex-col justify-between" class="w-5/12 mx-4 flex flex-col justify-between"
v-for="invoice in invoices" v-for="invoice in invoices"
:key="invoice.title" :key="invoice.title"
> >

View File

@ -22,11 +22,7 @@
</Button> </Button>
</template> </template>
</PageHeader> </PageHeader>
<div <div v-if="doc" class="flex justify-center flex-1 mb-8 mt-2">
v-if="doc"
class="flex justify-center flex-1 mb-8 mt-2"
:class="doc.submitted && 'pointer-events-none'"
>
<div <div
class="border rounded-lg shadow h-full flex flex-col justify-between" class="border rounded-lg shadow h-full flex flex-col justify-between"
style="width: 600px" style="width: 600px"
@ -45,6 +41,8 @@
@change="value => doc.set('entryType', value)" @change="value => doc.set('entryType', value)"
input-class="bg-gray-100 px-3 py-2 text-base" input-class="bg-gray-100 px-3 py-2 text-base"
:show-label="true" :show-label="true"
:read-only="doc.submitted"
:class="doc.submitted && 'pointer-events-none'"
/> />
<FormControl <FormControl
class="mt-2" class="mt-2"
@ -54,6 +52,8 @@
@change="value => doc.set('date', value)" @change="value => doc.set('date', value)"
input-class="bg-gray-100 px-3 py-2 text-base" input-class="bg-gray-100 px-3 py-2 text-base"
:show-label="true" :show-label="true"
:read-only="doc.submitted"
:class="doc.submitted && 'pointer-events-none'"
/> />
</div> </div>
<div class="w-1/3"> <div class="w-1/3">
@ -64,6 +64,8 @@
@change="value => doc.set('referenceNumber', value)" @change="value => doc.set('referenceNumber', value)"
input-class="bg-gray-100 p-2 text-base" input-class="bg-gray-100 p-2 text-base"
:show-label="true" :show-label="true"
:read-only="doc.submitted"
:class="doc.submitted && 'pointer-events-none'"
/> />
<FormControl <FormControl
class="mt-2" class="mt-2"
@ -73,6 +75,8 @@
@change="value => doc.set('referenceDate', value)" @change="value => doc.set('referenceDate', value)"
input-class="bg-gray-100 px-3 py-2 text-base" input-class="bg-gray-100 px-3 py-2 text-base"
:show-label="true" :show-label="true"
:read-only="doc.submitted"
:class="doc.submitted && 'pointer-events-none'"
/> />
</div> </div>
</div> </div>
@ -82,6 +86,7 @@
:df="meta.getField('accounts')" :df="meta.getField('accounts')"
:value="doc.accounts" :value="doc.accounts"
:showHeader="true" :showHeader="true"
:max-rows-before-overflow="4"
@change="value => doc.set('accounts', value)" @change="value => doc.set('accounts', value)"
:read-only="doc.submitted" :read-only="doc.submitted"
/> />
@ -97,6 +102,8 @@
:df="meta.getField('userRemark')" :df="meta.getField('userRemark')"
:value="doc.userRemark" :value="doc.userRemark"
@change="value => doc.set('userRemark', value)" @change="value => doc.set('userRemark', value)"
:class="doc.submitted && 'pointer-events-none'"
:read-only="doc.submitted"
/> />
</div> </div>
<div class="text-right font-semibold text-green-700 px-3"> <div class="text-right font-semibold text-green-700 px-3">

View File

@ -90,24 +90,20 @@ export default {
let html = this.$refs.printContainer.innerHTML; let html = this.$refs.printContainer.innerHTML;
makePDF(html, destination); makePDF(html, destination);
}, },
getSavePath() { async getSavePath() {
return new Promise(resolve => { const options = {
remote.dialog.showSaveDialog(
remote.getCurrentWindow(),
{
title: this._('Select folder'), title: this._('Select folder'),
defaultPath: `${this.name}.pdf` defaultPath: `${this.name}.pdf`
}, };
filePath => {
let { filePath } = await remote.dialog.showSaveDialog(options);
if (filePath) { if (filePath) {
if (!filePath.endsWith('.pdf')) { if (!filePath.endsWith('.pdf')) {
filePath = filePath + '.pdf'; filePath = filePath + '.pdf';
} }
resolve(filePath);
} }
}
); return filePath;
});
} }
} }
}; };

View File

@ -9,15 +9,13 @@ import router from '@/router';
import Avatar from '@/components/Avatar'; import Avatar from '@/components/Avatar';
import config from '@/config'; import config from '@/config';
export function createNewDatabase() { export async function createNewDatabase() {
return new Promise(resolve => { const options = {
remote.dialog.showSaveDialog(
remote.getCurrentWindow(),
{
title: _('Select folder'), title: _('Select folder'),
defaultPath: 'frappe-books.db' defaultPath: 'frappe-books.db'
}, };
filePath => {
let { filePath } = await remote.dialog.showSaveDialog(options);
if (filePath) { if (filePath) {
if (!filePath.endsWith('.db')) { if (!filePath.endsWith('.db')) {
filePath = filePath + '.db'; filePath = filePath + '.db';
@ -31,37 +29,30 @@ export function createNewDatabase() {
label: _('Overwrite'), label: _('Overwrite'),
action() { action() {
fs.unlinkSync(filePath); fs.unlinkSync(filePath);
resolve(filePath); return filePath;
} }
}, },
{ label: _('Cancel'), action() {} } { label: _('Cancel'), action() {} }
] ]
}); });
} else { } else {
resolve(filePath); return filePath;
} }
} }
}
);
});
} }
export function loadExistingDatabase() { export async function loadExistingDatabase() {
return new Promise(resolve => { const options = {
remote.dialog.showOpenDialog(
remote.getCurrentWindow(),
{
title: _('Select file'), title: _('Select file'),
properties: ['openFile'], properties: ['openFile'],
filters: [{ name: 'SQLite DB File', extensions: ['db'] }] filters: [{ name: 'SQLite DB File', extensions: ['db'] }]
}, };
files => {
if (files && files[0]) { let { filePaths } = await remote.dialog.showOpenDialog(options);
resolve(files[0]);
if (filePaths && filePaths[0]) {
return filePaths[0]
} }
}
);
});
} }
export async function connectToLocalDatabase(filepath) { export async function connectToLocalDatabase(filepath) {
@ -90,22 +81,25 @@ export async function connectToLocalDatabase(filepath) {
config.set('lastSelectedFilePath', filepath); config.set('lastSelectedFilePath', filepath);
} }
export function showMessageDialog({ message, description, buttons = [] }) { export async function showMessageDialog({
message,
description,
buttons = []
}) {
let buttonLabels = buttons.map(a => a.label); let buttonLabels = buttons.map(a => a.label);
remote.dialog.showMessageBox( const { response } = await remote.dialog.showMessageBox(
remote.getCurrentWindow(), remote.getCurrentWindow(),
{ {
message, message,
detail: description, detail: description,
buttons: buttonLabels buttons: buttonLabels
}, }
response => { );
let button = buttons[response]; let button = buttons[response];
if (button && button.action) { if (button && button.action) {
button.action(); button.action();
} }
}
);
} }
export function deleteDocWithPrompt(doc) { export function deleteDocWithPrompt(doc) {
@ -203,6 +197,16 @@ export function handleErrorWithDialog(e, doc) {
throw e; throw e;
} }
// NOTE: a hack to find all the css from the current document and inject it to the print version
// remove this if you are able to fix and get the default css loading on the page
function injectCSS(contents) {
const styles = document.getElementsByTagName('style');
for (let style of styles) {
contents.insertCSS(style.innerHTML);
}
}
export function makePDF(html, destination) { export function makePDF(html, destination) {
const { BrowserWindow } = remote; const { BrowserWindow } = remote;
@ -211,7 +215,8 @@ export function makePDF(html, destination) {
height: 842, height: 842,
show: false, show: false,
webPreferences: { webPreferences: {
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
enableRemoteModule: true
} }
}); });
@ -234,23 +239,24 @@ export function makePDF(html, destination) {
printWindow.webContents.executeJavaScript(code); printWindow.webContents.executeJavaScript(code);
return new Promise(resolve => { const printOptions = {
printWindow.webContents.on('did-finish-load', () => {
printWindow.webContents.printToPDF(
{
marginsType: 1, // no margin marginsType: 1, // no margin
pageSize: 'A4', pageSize: 'A4',
printBackground: true printBackground: true,
}, printBackgrounds: true,
(error, data) => { printSelectionOnly: false
if (error) throw error; };
return new Promise(resolve => {
printWindow.webContents.on('did-finish-load', () => {
injectCSS(printWindow.webContents);
printWindow.webContents.printToPDF(printOptions).then(data => {
printWindow.close(); printWindow.close();
fs.writeFile(destination, data, error => { fs.writeFile(destination, data, error => {
if (error) throw error; if (error) throw error;
resolve(shell.openItem(destination)); resolve(shell.openItem(destination));
}); });
} });
);
}); });
}); });
} }