@@ -0,0 +1,107 @@ | |||
<template> | |||
<div class="h-100"> | |||
<div class="row"> | |||
<div class="col"> | |||
<div ref="doc-select"></div> | |||
</div> | |||
<div class="col"> | |||
<div ref="preview-type"></div> | |||
</div> | |||
<div class="col d-flex"> | |||
<a v-if="url" class="btn btn-default btn-sm btn-new-tab" target="_blank" :href="url"> | |||
{{ __("Open in a new tab") }} | |||
</a> | |||
</div> | |||
</div> | |||
<div v-if="url && !preview_loaded">Generating preview...</div> | |||
<iframe | |||
:src="url" | |||
v-if="url" | |||
v-show="preview_loaded" | |||
class="preview-iframe" | |||
@load="preview_loaded = true" | |||
></iframe> | |||
</div> | |||
</template> | |||
<script> | |||
import { storeMixin } from "./store"; | |||
export default { | |||
name: "Preview", | |||
mixins: [storeMixin], | |||
data() { | |||
return { | |||
type: "PDF", | |||
docname: null, | |||
preview_loaded: false | |||
}; | |||
}, | |||
mounted() { | |||
this.doc_select = frappe.ui.form.make_control({ | |||
parent: this.$refs["doc-select"], | |||
df: { | |||
label: __("Select {0}", [__(this.doctype)]), | |||
fieldname: "docname", | |||
fieldtype: "Link", | |||
options: this.doctype, | |||
change: () => { | |||
this.docname = this.doc_select.get_value(); | |||
} | |||
}, | |||
render_input: true | |||
}); | |||
this.preview_type = frappe.ui.form.make_control({ | |||
parent: this.$refs["preview-type"], | |||
df: { | |||
label: __("Preview type"), | |||
fieldname: "docname", | |||
fieldtype: "Select", | |||
options: ["PDF", "HTML"], | |||
change: () => { | |||
this.type = this.preview_type.get_value(); | |||
} | |||
}, | |||
render_input: true | |||
}); | |||
this.preview_type.set_value(this.type); | |||
this.get_default_docname().then( | |||
docname => docname && this.doc_select.set_value(docname) | |||
); | |||
}, | |||
methods: { | |||
get_default_docname() { | |||
return frappe.db.get_list(this.doctype, { limit: 1 }).then(doc => { | |||
return doc.length > 0 ? doc[0].name : null; | |||
}); | |||
} | |||
}, | |||
computed: { | |||
doctype() { | |||
return this.print_format.doc_type; | |||
}, | |||
url() { | |||
if (!this.docname) return null; | |||
let params = new URLSearchParams(); | |||
params.append("doctype", this.doctype); | |||
params.append("name", this.docname); | |||
params.append("print_format", this.print_format.name); | |||
let url = | |||
this.type == "PDF" | |||
? `/api/method/frappe.utils.weasyprint.download_pdf` | |||
: "/printpreview"; | |||
return `${url}?${params.toString()}`; | |||
} | |||
} | |||
}; | |||
</script> | |||
<style scoped> | |||
.preview-iframe { | |||
width: 100%; | |||
height: 96%; | |||
border: none; | |||
border-radius: var(--border-radius); | |||
} | |||
.btn-new-tab { | |||
margin-top: auto; | |||
margin-bottom: 1.2rem; | |||
} | |||
</style> |
@@ -4,13 +4,17 @@ | |||
<PrintFormatControls /> | |||
</div> | |||
<div class="print-format-container col-9"> | |||
<PrintFormat /> | |||
<keep-alive> | |||
<Preview v-if="show_preview" /> | |||
<PrintFormat v-else /> | |||
</keep-alive> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import PrintFormat from "./PrintFormat.vue"; | |||
import Preview from "./Preview.vue"; | |||
import PrintFormatControls from "./PrintFormatControls.vue"; | |||
import { getStore } from "./store"; | |||
@@ -19,7 +23,13 @@ export default { | |||
props: ["print_format_name"], | |||
components: { | |||
PrintFormat, | |||
PrintFormatControls | |||
PrintFormatControls, | |||
Preview | |||
}, | |||
data() { | |||
return { | |||
show_preview: false | |||
}; | |||
}, | |||
provide() { | |||
return { | |||
@@ -29,6 +39,11 @@ export default { | |||
mounted() { | |||
this.$store.fetch(); | |||
}, | |||
methods: { | |||
toggle_preview() { | |||
this.show_preview = !this.show_preview; | |||
} | |||
}, | |||
computed: { | |||
$store() { | |||
return getStore(this.print_format_name); | |||
@@ -6,8 +6,8 @@ class PrintFormatBuilder { | |||
this.page = page; | |||
this.print_format = print_format; | |||
this.page.clear_actions() | |||
this.page.clear_custom_actions() | |||
this.page.clear_actions(); | |||
this.page.clear_custom_actions(); | |||
this.page.set_title(__("Editing {0}", [this.print_format])); | |||
this.page.set_primary_action(__("Save changes"), () => { | |||
@@ -17,10 +17,8 @@ class PrintFormatBuilder { | |||
this.$component.$store.reset_changes(); | |||
}); | |||
this.page.add_button( | |||
__("Preview"), | |||
() => { | |||
this.preview(); | |||
}, | |||
__("Toggle Preview"), | |||
() => this.$component.toggle_preview(), | |||
{ icon: "small-file" } | |||
); | |||
@@ -35,46 +33,6 @@ class PrintFormatBuilder { | |||
}); | |||
this.$component = $vm.$children[0]; | |||
} | |||
async preview() { | |||
let doctype = this.$component.$store.print_format.doc_type; | |||
let default_doc = await frappe.db.get_list(doctype, { | |||
limit: 1 | |||
}); | |||
let d = new frappe.ui.Dialog({ | |||
title: __("Preview Print Format"), | |||
fields: [ | |||
{ | |||
label: __("Type"), | |||
fieldname: "type", | |||
fieldtype: "Select", | |||
options: ["PDF", "HTML"], | |||
default: "PDF" | |||
}, | |||
{ | |||
label: __("Select Document"), | |||
fieldname: "docname", | |||
fieldtype: "Link", | |||
options: doctype, | |||
reqd: 1, | |||
default: default_doc.length > 0 ? default_doc[0].name : null | |||
} | |||
], | |||
primary_action: ({ docname, type }) => { | |||
let params = new URLSearchParams(); | |||
params.append("doctype", doctype); | |||
params.append("name", docname); | |||
params.append("print_format", this.print_format); | |||
let url = | |||
type == "PDF" | |||
? `/api/method/frappe.utils.weasyprint.download_pdf` | |||
: "/printpreview"; | |||
window.open(`${url}?${params.toString()}`, "_blank"); | |||
} | |||
}); | |||
d.show(); | |||
} | |||
} | |||
frappe.provide("frappe.ui"); | |||