mirror of
https://github.com/frappe/books.git
synced 2024-11-14 01:14:03 +00:00
Merge pull request #645 from frappe/print-view-issues
fix: print view issues
This commit is contained in:
commit
0eb0f81a88
@ -42,8 +42,8 @@ export default function registerIpcMainActionListeners(main: Main) {
|
|||||||
|
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
IPC_ACTIONS.SAVE_HTML_AS_PDF,
|
IPC_ACTIONS.SAVE_HTML_AS_PDF,
|
||||||
async (event, html, savePath) => {
|
async (event, html, savePath, width: number, height: number) => {
|
||||||
return await saveHtmlAsPdf(html, savePath, app);
|
return await saveHtmlAsPdf(html, savePath, app, width, height);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2,18 +2,12 @@ import { App, BrowserWindow } from 'electron';
|
|||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
const PRINT_OPTIONS = {
|
|
||||||
marginsType: 1, // no margin
|
|
||||||
pageSize: 'A4',
|
|
||||||
printBackground: true,
|
|
||||||
printBackgrounds: true,
|
|
||||||
printSelectionOnly: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function saveHtmlAsPdf(
|
export async function saveHtmlAsPdf(
|
||||||
html: string,
|
html: string,
|
||||||
savePath: string,
|
savePath: string,
|
||||||
app: App
|
app: App,
|
||||||
|
width: number, // centimeters
|
||||||
|
height: number // centimeters
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
/**
|
/**
|
||||||
* Store received html as a file in a tempdir,
|
* Store received html as a file in a tempdir,
|
||||||
@ -24,7 +18,17 @@ export async function saveHtmlAsPdf(
|
|||||||
const htmlPath = path.join(tempRoot, `${filename}.html`);
|
const htmlPath = path.join(tempRoot, `${filename}.html`);
|
||||||
await fs.writeFile(htmlPath, html, { encoding: 'utf-8' });
|
await fs.writeFile(htmlPath, html, { encoding: 'utf-8' });
|
||||||
|
|
||||||
const printWindow = getInitializedPrintWindow(htmlPath);
|
const printWindow = getInitializedPrintWindow(htmlPath, width, height);
|
||||||
|
const printOptions = {
|
||||||
|
marginsType: 1, // no margin
|
||||||
|
pageSize: {
|
||||||
|
height: height * 10_000, // micrometers
|
||||||
|
width: width * 10_000, // micrometers
|
||||||
|
},
|
||||||
|
printBackground: true,
|
||||||
|
printBackgrounds: true,
|
||||||
|
printSelectionOnly: false,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* After the printWindow content is ready, save as pdf and
|
* After the printWindow content is ready, save as pdf and
|
||||||
@ -32,7 +36,7 @@ export async function saveHtmlAsPdf(
|
|||||||
*/
|
*/
|
||||||
return await new Promise((resolve) => {
|
return await new Promise((resolve) => {
|
||||||
printWindow.webContents.once('did-finish-load', () => {
|
printWindow.webContents.once('did-finish-load', () => {
|
||||||
printWindow.webContents.printToPDF(PRINT_OPTIONS).then((data) => {
|
printWindow.webContents.printToPDF(printOptions).then((data) => {
|
||||||
fs.writeFile(savePath, data).then(() => {
|
fs.writeFile(savePath, data).then(() => {
|
||||||
printWindow.close();
|
printWindow.close();
|
||||||
fs.unlink(htmlPath).then(() => {
|
fs.unlink(htmlPath).then(() => {
|
||||||
@ -44,10 +48,14 @@ export async function saveHtmlAsPdf(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInitializedPrintWindow(printFilePath: string) {
|
function getInitializedPrintWindow(
|
||||||
|
printFilePath: string,
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
) {
|
||||||
const printWindow = new BrowserWindow({
|
const printWindow = new BrowserWindow({
|
||||||
width: 595,
|
width: Math.floor(width * 28.333333), // pixels
|
||||||
height: 842,
|
height: Math.floor(height * 28.333333), // pixels
|
||||||
show: false,
|
show: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ import { Fyo } from 'fyo';
|
|||||||
export class PrintTemplate extends Doc {
|
export class PrintTemplate extends Doc {
|
||||||
name?: string;
|
name?: string;
|
||||||
type?: string;
|
type?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
template?: string;
|
template?: string;
|
||||||
isCustom?: boolean;
|
isCustom?: boolean;
|
||||||
|
|
||||||
|
@ -23,6 +23,18 @@
|
|||||||
"fieldtype": "Text",
|
"fieldtype": "Text",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "height",
|
||||||
|
"label": "Height (in cm)",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"default": 29.7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "width",
|
||||||
|
"label": "Width (in cm)",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"default": 21
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "isCustom",
|
"fieldname": "isCustom",
|
||||||
"label": "Is Custom",
|
"label": "Is Custom",
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
:template="printProps.template"
|
:template="printProps.template"
|
||||||
:values="printProps.values"
|
:values="printProps.values"
|
||||||
:scale="scale"
|
:scale="scale"
|
||||||
|
:width="templateDoc?.width"
|
||||||
|
:height="templateDoc?.height"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<ScaledContainer
|
<ScaledContainer
|
||||||
:scale="Math.max(scale, 0.1)"
|
:scale="Math.max(scale, 0.1)"
|
||||||
|
:width="width"
|
||||||
|
:height="height"
|
||||||
ref="scaledContainer"
|
ref="scaledContainer"
|
||||||
class="mx-auto shadow-lg border"
|
class="mx-auto shadow-lg border"
|
||||||
>
|
>
|
||||||
@ -69,6 +71,8 @@ export default defineComponent({
|
|||||||
props: {
|
props: {
|
||||||
template: { type: String, required: true },
|
template: { type: String, required: true },
|
||||||
scale: { type: Number, default: 0.65 },
|
scale: { type: Number, default: 0.65 },
|
||||||
|
width: { type: Number, default: 21 },
|
||||||
|
height: { type: Number, default: 29.7 },
|
||||||
values: {
|
values: {
|
||||||
type: Object as PropType<PrintValues>,
|
type: Object as PropType<PrintValues>,
|
||||||
required: true,
|
required: true,
|
||||||
@ -144,7 +148,12 @@ export default defineComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await getPathAndMakePDF(name ?? this.t`Entry`, innerHTML);
|
await getPathAndMakePDF(
|
||||||
|
name ?? this.t`Entry`,
|
||||||
|
innerHTML,
|
||||||
|
this.width,
|
||||||
|
this.height
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -165,7 +174,7 @@ export default defineComponent({
|
|||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
} as {} /** to silence :is type check */;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: { ScaledContainer, ErrorBoundary },
|
components: { ScaledContainer, ErrorBoundary },
|
||||||
|
@ -18,20 +18,20 @@ import { defineComponent } from 'vue';
|
|||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
height: { type: String, default: '29.7cm' },
|
height: { type: Number, default: 29.7 },
|
||||||
width: { type: String, default: '21cm' },
|
width: { type: Number, default: 21 },
|
||||||
scale: { type: Number, default: 0.65 },
|
scale: { type: Number, default: 0.65 },
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
innerContainerStyle(): Record<string, string> {
|
innerContainerStyle(): Record<string, string> {
|
||||||
const style: Record<string, string> = {};
|
const style: Record<string, string> = {};
|
||||||
style['width'] = this.width;
|
style['width'] = this.width + 'cm';
|
||||||
style['height'] = this.height;
|
style['height'] = this.height + 'cm';
|
||||||
style['transform'] = `scale(${this.scale})`;
|
style['transform'] = `scale(${this.scale})`;
|
||||||
style['margin-top'] = `calc(-1 * (${this.height} * ${
|
style['margin-top'] = `calc(-1 * (${this.height}cm * ${
|
||||||
1 - this.scale
|
1 - this.scale
|
||||||
}) / 2)`;
|
}) / 2)`;
|
||||||
style['margin-left'] = `calc(-1 * (${this.width} * ${
|
style['margin-left'] = `calc(-1 * (${this.width}cm * ${
|
||||||
1 - this.scale
|
1 - this.scale
|
||||||
}) / 2)`;
|
}) / 2)`;
|
||||||
|
|
||||||
@ -39,8 +39,8 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
outerContainerStyle(): Record<string, string> {
|
outerContainerStyle(): Record<string, string> {
|
||||||
const style: Record<string, string> = {};
|
const style: Record<string, string> = {};
|
||||||
style['height'] = `calc(${this.scale} * ${this.height})`;
|
style['height'] = `calc(${this.scale} * ${this.height}cm)`;
|
||||||
style['width'] = `calc(${this.scale} * ${this.width})`;
|
style['width'] = `calc(${this.scale} * ${this.width}cm)`;
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
},
|
},
|
||||||
|
265
src/pages/TemplateBuilder/SetPrintSize.vue
Normal file
265
src/pages/TemplateBuilder/SetPrintSize.vue
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
<template>
|
||||||
|
<div class="w-form">
|
||||||
|
<FormHeader :form-title="t`Set Print Size`" />
|
||||||
|
<hr />
|
||||||
|
<div class="p-4 w-full flex flex-col gap-4">
|
||||||
|
<p class="text-base text-gray-900">
|
||||||
|
{{
|
||||||
|
t`Select a pre-defined page size, or set a custom page size for your Print Template.`
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<Select
|
||||||
|
:df="df"
|
||||||
|
:value="size"
|
||||||
|
@change="sizeChange"
|
||||||
|
:border="true"
|
||||||
|
:show-label="true"
|
||||||
|
/>
|
||||||
|
<div class="flex gap-4 w-full">
|
||||||
|
<Float
|
||||||
|
class="w-full"
|
||||||
|
:df="fyo.getField('PrintTemplate', 'height')"
|
||||||
|
:border="true"
|
||||||
|
:show-label="true"
|
||||||
|
:value="height"
|
||||||
|
@change="(v) => valueChange(v, 'height')"
|
||||||
|
/>
|
||||||
|
<Float
|
||||||
|
class="w-full"
|
||||||
|
:df="fyo.getField('PrintTemplate', 'width')"
|
||||||
|
:border="true"
|
||||||
|
:show-label="true"
|
||||||
|
:value="width"
|
||||||
|
@change="(v) => valueChange(v, 'width')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex border-t p-4">
|
||||||
|
<Button class="ml-auto" type="primary" @click="done">{{
|
||||||
|
t`Done`
|
||||||
|
}}</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { PrintTemplate } from 'models/baseModels/PrintTemplate';
|
||||||
|
import { OptionField } from 'schemas/types';
|
||||||
|
import Button from 'src/components/Button.vue';
|
||||||
|
import Float from 'src/components/Controls/Float.vue';
|
||||||
|
import Select from 'src/components/Controls/Select.vue';
|
||||||
|
import FormHeader from 'src/components/FormHeader.vue';
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
const printSizes = [
|
||||||
|
'A0',
|
||||||
|
'A1',
|
||||||
|
'A2',
|
||||||
|
'A3',
|
||||||
|
'A4',
|
||||||
|
'A5',
|
||||||
|
'A6',
|
||||||
|
'A7',
|
||||||
|
'A8',
|
||||||
|
'A9',
|
||||||
|
'B0',
|
||||||
|
'B1',
|
||||||
|
'B2',
|
||||||
|
'B3',
|
||||||
|
'B4',
|
||||||
|
'B5',
|
||||||
|
'B6',
|
||||||
|
'B7',
|
||||||
|
'B8',
|
||||||
|
'B9',
|
||||||
|
'Letter',
|
||||||
|
'Legal',
|
||||||
|
'Executive',
|
||||||
|
'C5E',
|
||||||
|
'Comm10',
|
||||||
|
'DLE',
|
||||||
|
'Folio',
|
||||||
|
'Ledger',
|
||||||
|
'Tabloid',
|
||||||
|
'Custom',
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
type SizeName = typeof printSizes[number];
|
||||||
|
const paperSizeMap: Record<SizeName, { width: number; height: number }> = {
|
||||||
|
A0: {
|
||||||
|
width: 84.1,
|
||||||
|
height: 118.9,
|
||||||
|
},
|
||||||
|
A1: {
|
||||||
|
width: 59.4,
|
||||||
|
height: 84.1,
|
||||||
|
},
|
||||||
|
A2: {
|
||||||
|
width: 42,
|
||||||
|
height: 59.4,
|
||||||
|
},
|
||||||
|
A3: {
|
||||||
|
width: 29.7,
|
||||||
|
height: 42,
|
||||||
|
},
|
||||||
|
A4: {
|
||||||
|
width: 21,
|
||||||
|
height: 29.7,
|
||||||
|
},
|
||||||
|
A5: {
|
||||||
|
width: 14.8,
|
||||||
|
height: 21,
|
||||||
|
},
|
||||||
|
A6: {
|
||||||
|
width: 10.5,
|
||||||
|
height: 14.8,
|
||||||
|
},
|
||||||
|
A7: {
|
||||||
|
width: 7.4,
|
||||||
|
height: 10.5,
|
||||||
|
},
|
||||||
|
A8: {
|
||||||
|
width: 5.2,
|
||||||
|
height: 7.4,
|
||||||
|
},
|
||||||
|
A9: {
|
||||||
|
width: 3.7,
|
||||||
|
height: 5.2,
|
||||||
|
},
|
||||||
|
B0: {
|
||||||
|
width: 100,
|
||||||
|
height: 141.4,
|
||||||
|
},
|
||||||
|
B1: {
|
||||||
|
width: 70.7,
|
||||||
|
height: 100,
|
||||||
|
},
|
||||||
|
B2: {
|
||||||
|
width: 50,
|
||||||
|
height: 70.7,
|
||||||
|
},
|
||||||
|
B3: {
|
||||||
|
width: 35.3,
|
||||||
|
height: 50,
|
||||||
|
},
|
||||||
|
B4: {
|
||||||
|
width: 25,
|
||||||
|
height: 35.3,
|
||||||
|
},
|
||||||
|
B5: {
|
||||||
|
width: 17.6,
|
||||||
|
height: 25,
|
||||||
|
},
|
||||||
|
B6: {
|
||||||
|
width: 12.5,
|
||||||
|
height: 17.6,
|
||||||
|
},
|
||||||
|
B7: {
|
||||||
|
width: 8.8,
|
||||||
|
height: 12.5,
|
||||||
|
},
|
||||||
|
B8: {
|
||||||
|
width: 6.2,
|
||||||
|
height: 8.8,
|
||||||
|
},
|
||||||
|
B9: {
|
||||||
|
width: 4.4,
|
||||||
|
height: 6.2,
|
||||||
|
},
|
||||||
|
Letter: {
|
||||||
|
width: 21.59,
|
||||||
|
height: 27.94,
|
||||||
|
},
|
||||||
|
Legal: {
|
||||||
|
width: 21.59,
|
||||||
|
height: 35.56,
|
||||||
|
},
|
||||||
|
Executive: {
|
||||||
|
width: 19.05,
|
||||||
|
height: 25.4,
|
||||||
|
},
|
||||||
|
C5E: {
|
||||||
|
width: 16.3,
|
||||||
|
height: 22.9,
|
||||||
|
},
|
||||||
|
Comm10: {
|
||||||
|
width: 10.5,
|
||||||
|
height: 24.1,
|
||||||
|
},
|
||||||
|
DLE: {
|
||||||
|
width: 11,
|
||||||
|
height: 22,
|
||||||
|
},
|
||||||
|
Folio: {
|
||||||
|
width: 21,
|
||||||
|
height: 33,
|
||||||
|
},
|
||||||
|
Ledger: {
|
||||||
|
width: 43.2,
|
||||||
|
height: 27.9,
|
||||||
|
},
|
||||||
|
Tabloid: {
|
||||||
|
width: 27.9,
|
||||||
|
height: 43.2,
|
||||||
|
},
|
||||||
|
Custom: {
|
||||||
|
width: -1,
|
||||||
|
height: -1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: { doc: { type: PrintTemplate, required: true } },
|
||||||
|
data() {
|
||||||
|
return { size: 'A4', width: 21, height: 29.7 };
|
||||||
|
},
|
||||||
|
components: { Float, FormHeader, Select, Button },
|
||||||
|
mounted() {
|
||||||
|
this.width = this.doc.width ?? 21;
|
||||||
|
this.height = this.doc.height ?? 29.7;
|
||||||
|
|
||||||
|
this.size = '';
|
||||||
|
Object.entries(paperSizeMap).forEach(([name, { width, height }]) => {
|
||||||
|
if (this.width === width && this.height === height) {
|
||||||
|
this.size = name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.size ||= 'Custom';
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
sizeChange(v: string) {
|
||||||
|
const size = paperSizeMap[v as SizeName];
|
||||||
|
if (!size) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.height = size.height;
|
||||||
|
this.width = size.width;
|
||||||
|
},
|
||||||
|
valueChange(v: number, name: 'width' | 'height') {
|
||||||
|
if (this[name] === v) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.size = 'Custom';
|
||||||
|
this[name] = v;
|
||||||
|
},
|
||||||
|
done() {
|
||||||
|
this.doc.set('width', this.width);
|
||||||
|
this.doc.set('height', this.height);
|
||||||
|
this.$emit('done');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
df(): OptionField {
|
||||||
|
return {
|
||||||
|
label: 'Page Size',
|
||||||
|
fieldname: 'size',
|
||||||
|
fieldtype: 'Select',
|
||||||
|
options: printSizes.map((value) => ({ value, label: value })),
|
||||||
|
default: 'A4',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
@ -49,6 +49,8 @@
|
|||||||
:template="doc.template!"
|
:template="doc.template!"
|
||||||
:values="values!"
|
:values="values!"
|
||||||
:scale="scale"
|
:scale="scale"
|
||||||
|
:height="doc.height"
|
||||||
|
:width="doc.width"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -203,6 +205,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Modal
|
||||||
|
v-if="doc"
|
||||||
|
:open-modal="showSizeModal"
|
||||||
|
@closemodal="showSizeModal = !showSizeModal"
|
||||||
|
>
|
||||||
|
<SetPrintSize :doc="doc" @done="showSizeModal = !showSizeModal" />
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@ -216,6 +225,7 @@ import Button from 'src/components/Button.vue';
|
|||||||
import FormControl from 'src/components/Controls/FormControl.vue';
|
import FormControl from 'src/components/Controls/FormControl.vue';
|
||||||
import DropdownWithActions from 'src/components/DropdownWithActions.vue';
|
import DropdownWithActions from 'src/components/DropdownWithActions.vue';
|
||||||
import HorizontalResizer from 'src/components/HorizontalResizer.vue';
|
import HorizontalResizer from 'src/components/HorizontalResizer.vue';
|
||||||
|
import Modal from 'src/components/Modal.vue';
|
||||||
import PageHeader from 'src/components/PageHeader.vue';
|
import PageHeader from 'src/components/PageHeader.vue';
|
||||||
import ShortcutKeys from 'src/components/ShortcutKeys.vue';
|
import ShortcutKeys from 'src/components/ShortcutKeys.vue';
|
||||||
import { handleErrorWithDialog } from 'src/errorHandling';
|
import { handleErrorWithDialog } from 'src/errorHandling';
|
||||||
@ -231,12 +241,12 @@ import {
|
|||||||
import { docsPathRef, showSidebar } from 'src/utils/refs';
|
import { docsPathRef, showSidebar } from 'src/utils/refs';
|
||||||
import { DocRef, PrintValues } from 'src/utils/types';
|
import { DocRef, PrintValues } from 'src/utils/types';
|
||||||
import {
|
import {
|
||||||
|
ShortcutKey,
|
||||||
focusOrSelectFormControl,
|
focusOrSelectFormControl,
|
||||||
getActionsForDoc,
|
getActionsForDoc,
|
||||||
getDocFromNameIfExistsElseNew,
|
getDocFromNameIfExistsElseNew,
|
||||||
openSettings,
|
openSettings,
|
||||||
selectTextFile,
|
selectTextFile,
|
||||||
ShortcutKey,
|
|
||||||
} from 'src/utils/ui';
|
} from 'src/utils/ui';
|
||||||
import { useDocShortcuts } from 'src/utils/vueUtils';
|
import { useDocShortcuts } from 'src/utils/vueUtils';
|
||||||
import { getMapFromList } from 'utils/index';
|
import { getMapFromList } from 'utils/index';
|
||||||
@ -244,6 +254,7 @@ import { computed, defineComponent, inject, ref } from 'vue';
|
|||||||
import PrintContainer from './PrintContainer.vue';
|
import PrintContainer from './PrintContainer.vue';
|
||||||
import TemplateBuilderHint from './TemplateBuilderHint.vue';
|
import TemplateBuilderHint from './TemplateBuilderHint.vue';
|
||||||
import TemplateEditor from './TemplateEditor.vue';
|
import TemplateEditor from './TemplateEditor.vue';
|
||||||
|
import SetPrintSize from './SetPrintSize.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: { name: String },
|
props: { name: String },
|
||||||
@ -257,6 +268,8 @@ export default defineComponent({
|
|||||||
FormControl,
|
FormControl,
|
||||||
TemplateBuilderHint,
|
TemplateBuilderHint,
|
||||||
ShortcutKeys,
|
ShortcutKeys,
|
||||||
|
Modal,
|
||||||
|
SetPrintSize,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const doc = ref(null) as DocRef<PrintTemplate>;
|
const doc = ref(null) as DocRef<PrintTemplate>;
|
||||||
@ -286,6 +299,7 @@ export default defineComponent({
|
|||||||
scale: 0.6,
|
scale: 0.6,
|
||||||
panelWidth: 22 /** rem */ * 16 /** px */,
|
panelWidth: 22 /** rem */ * 16 /** px */,
|
||||||
templateChanged: false,
|
templateChanged: false,
|
||||||
|
showSizeModal: false,
|
||||||
preEditMode: {
|
preEditMode: {
|
||||||
scale: 0.6,
|
scale: 0.6,
|
||||||
showSidebar: true,
|
showSidebar: true,
|
||||||
@ -297,6 +311,7 @@ export default defineComponent({
|
|||||||
hints?: Record<string, unknown>;
|
hints?: Record<string, unknown>;
|
||||||
values: null | PrintValues;
|
values: null | PrintValues;
|
||||||
displayDoc: PrintTemplate | null;
|
displayDoc: PrintTemplate | null;
|
||||||
|
showSizeModal: boolean;
|
||||||
scale: number;
|
scale: number;
|
||||||
panelWidth: number;
|
panelWidth: number;
|
||||||
templateChanged: boolean;
|
templateChanged: boolean;
|
||||||
@ -632,6 +647,14 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.doc.isCustom && !this.showSizeModal) {
|
||||||
|
actions.push({
|
||||||
|
label: this.t`Set Print Size`,
|
||||||
|
group: this.t`Action`,
|
||||||
|
action: () => (this.showSizeModal = true),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (this.doc.isCustom) {
|
if (this.doc.isCustom) {
|
||||||
actions.push({
|
actions.push({
|
||||||
label: this.t`Select Template File`,
|
label: this.t`Select Template File`,
|
||||||
|
@ -69,15 +69,22 @@ export async function saveData(data: string, savePath: string) {
|
|||||||
await ipcRenderer.invoke(IPC_ACTIONS.SAVE_DATA, data, savePath);
|
await ipcRenderer.invoke(IPC_ACTIONS.SAVE_DATA, data, savePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function showItemInFolder(filePath: string) {
|
export function showItemInFolder(filePath: string) {
|
||||||
await ipcRenderer.send(IPC_MESSAGES.SHOW_ITEM_IN_FOLDER, filePath);
|
ipcRenderer.send(IPC_MESSAGES.SHOW_ITEM_IN_FOLDER, filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function makePDF(html: string, savePath: string) {
|
export async function makePDF(
|
||||||
|
html: string,
|
||||||
|
savePath: string,
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
) {
|
||||||
const success = await ipcRenderer.invoke(
|
const success = await ipcRenderer.invoke(
|
||||||
IPC_ACTIONS.SAVE_HTML_AS_PDF,
|
IPC_ACTIONS.SAVE_HTML_AS_PDF,
|
||||||
html,
|
html,
|
||||||
savePath
|
savePath,
|
||||||
|
width,
|
||||||
|
height
|
||||||
);
|
);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -20,8 +20,9 @@ const printSettingsFields = [
|
|||||||
'email',
|
'email',
|
||||||
'phone',
|
'phone',
|
||||||
'address',
|
'address',
|
||||||
|
'companyName',
|
||||||
];
|
];
|
||||||
const accountingSettingsFields = ['companyName', 'gstin'];
|
const accountingSettingsFields = ['gstin'];
|
||||||
|
|
||||||
export async function getPrintTemplatePropValues(
|
export async function getPrintTemplatePropValues(
|
||||||
doc: Doc
|
doc: Doc
|
||||||
@ -212,14 +213,19 @@ async function getPrintTemplateDocValues(doc: Doc, fieldnames?: string[]) {
|
|||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPathAndMakePDF(name: string, innerHTML: string) {
|
export async function getPathAndMakePDF(
|
||||||
|
name: string,
|
||||||
|
innerHTML: string,
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
) {
|
||||||
const { filePath } = await getSavePath(name, 'pdf');
|
const { filePath } = await getSavePath(name, 'pdf');
|
||||||
if (!filePath) {
|
if (!filePath) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const html = constructPrintDocument(innerHTML);
|
const html = constructPrintDocument(innerHTML);
|
||||||
await makePDF(html, filePath);
|
await makePDF(html, filePath, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
function constructPrintDocument(innerHTML: string) {
|
function constructPrintDocument(innerHTML: string) {
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<!-- Right Section -->
|
<!-- Right Section -->
|
||||||
<section class="text-right">
|
<section class="text-right">
|
||||||
<p class="font-semibold text-xl" :style="{ color: print.color }">
|
<p class="font-semibold text-xl" :style="{ color: print.color }">
|
||||||
{{ doc.entryType }}
|
{{ doc.entryLabel }}
|
||||||
</p>
|
</p>
|
||||||
<p>{{ doc.name }}</p>
|
<p>{{ doc.name }}</p>
|
||||||
</section>
|
</section>
|
||||||
|
Loading…
Reference in New Issue
Block a user