feat: render print preview in an iframe

- use bootstrap 3
This commit is contained in:
prssanna 2020-11-09 15:40:11 +05:30
parent eff2388cee
commit 02508f7d4d
11 changed files with 299 additions and 391 deletions

View file

@ -36,11 +36,13 @@ frappe.ui.form.PrintView = class {
make() {
this.print_wrapper = this.page.main.empty().html(
`<div class="print-preview-wrapper"><div class="print-preview">
<div class="print-format"></div>
<iframe class="print-format-container" width="100%" frameBorder="0" scrolling="no"">
</iframe>
<div class="page-break-message text-muted text-center text-medium margin-top"></div>
</div>
</div>`
);
this.print_settings = frappe.model.get_doc(
':Print Settings',
'Print Settings'
@ -378,15 +380,14 @@ frappe.ui.form.PrintView = class {
}
preview() {
const $print_format = this.print_wrapper.find('.print-format').empty();
const $print_format = this.print_wrapper.find('iframe');
this.$print_format_body = $print_format.contents();
this.get_print_html((out) => {
if (!out.html) {
out.html = this.get_no_preview_html();
}
$print_format.html(out.html);
this.show_footer();
this.set_style(out.style);
this.setup_print_format_dom(out, $print_format);
const print_height = $print_format.get(0).offsetHeight;
const $message = this.wrapper.find('.page-break-message');
@ -402,6 +403,34 @@ frappe.ui.form.PrintView = class {
});
}
setup_print_format_dom(out, $print_format) {
this.$print_format_body.find('head').html(
`<style type="text/css">${out.style}</style>
<link href="${frappe.urllib.get_base_url()}/assets/css/printview.css" rel="stylesheet">`
);
this.$print_format_body.find('body').html(
`<div class="print-format">${out.html}</div>`
);
this.show_footer();
$print_format.css({
'min-height': this.$print_format_body.find('.print-format').height()
});
this.wrapper.find('.print-format').css({
display: 'flex',
flexDirection: 'column',
});
this.$print_format_body.find('.page-break').css({
display: 'flex',
'flex-direction': 'column',
flex: '1',
});
}
hide() {
if (this.frm.setup_done && this.frm.page.current_view_name === 'print') {
this.frm.page.set_view(
@ -415,21 +444,12 @@ frappe.ui.form.PrintView = class {
show_footer() {
// footer is hidden by default as reqd by pdf generation
// simple hack to show it in print preview
this.wrapper.find('.print-format').css({
display: 'flex',
flexDirection: 'column',
});
this.wrapper.find('.page-break').css({
display: 'flex',
'flex-direction': 'column',
flex: '1',
});
this.wrapper.find('#footer-html').attr(
this.$print_format_body.find('#footer-html').attr(
'style',
`
display: block !important;
order: 1;
margin-top: auto;
`
);
}

View file

@ -95,7 +95,10 @@
"public/css/desk-rtl.css",
"public/css/report-rtl.css"
],
"css/printview.css": "public/scss/print.scss",
"css/printview.css": [
"public/css/bootstrap.css",
"public/scss/print.scss"
],
"concat:js/libs.min.js": [
"public/js/lib/awesomplete/awesomplete.min.js",
"public/js/lib/Sortable.min.js",

View file

@ -1,22 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>{{ title }}</title>
<link href="{{ base_url }}/assets/frappe/css/bootstrap.css" rel="stylesheet">
<link type="text/css" rel="stylesheet"
href="{{ base_url }}/assets/frappe/css/font-awesome.css">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>{{ title }}</title>
<link href="{{ base_url }}/assets/css/printview.css" rel="stylesheet">
<style>
{{ print_css }}
</style>
</head>
<body>
<div class="print-format-gutter">
{% if print_settings.repeat_header_footer %}
</head>
<body>
<div class="print-format-gutter">
{% if print_settings.repeat_header_footer %}
<div id="footer-html" class="visible-pdf">
{% if print_settings.letter_head && print_settings.letter_head.footer %}
<div class="letter-head-footer">
@ -27,20 +25,20 @@
{{ __("Page {0} of {1}", [`<span class="page"></span>`, `<span class="topage"></span>`]) }}
</p>
</div>
{% endif %}
{% endif %}
<div class="print-format {% if landscape %} landscape {% endif %}"
<div class="print-format {% if landscape %} landscape {% endif %}"
{% if columns.length > 20 %}
style="font-size: 4.0pt"
{% endif %}
>
{% if print_settings.letter_head %}
<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
<div class="letter-head">{{ print_settings.letter_head.header }}</div>
</div>
{% endif %}
{{ content }}
</div>
</div>
</body>
{% if print_settings.letter_head %}
<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
<div class="letter-head">{{ print_settings.letter_head.header }}</div>
</div>
{% endif %}
{{ content }}
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,207 @@
:root {
--pink-900: #5B1E34;
--pink-800: #702440;
--pink-700: #97264F;
--pink-600: #D2326D;
--pink-500: #F2508B;
--pink-400: #F46B9E;
--pink-300: #F584AE;
--pink-200: #FAB9D1;
--pink-100: #FCDCE8;
--pink-50 : #FEEDF3;
--blue-900: #1A4469;
--blue-800: #154875;
--blue-700: #1366AE;
--blue-600: #1579D0;
--blue-500: #2490EF;
--blue-400: #50A6F2;
--blue-300: #7CBCF5;
--blue-200: #A7D3F9;
--blue-100: #D3E9FC;
--blue-50 : #F0F8FE;
--green-900: #2D401D;
--green-800: #44622A;
--green-700: #518B21;
--green-600: #68AB30;
--green-500: #8CCF54;
--green-400: #A5D97A;
--green-300: #BCE39B;
--green-200: #D2ECBD;
--green-100: #E9F6DE;
--green-50 : #F4FAEE;
--dark-green-900: #1F3E2B;
--dark-green-800: #29593B;
--dark-green-700: #286840;
--dark-green-600: #2E844E;
--dark-green-500: #2F9D58;
--dark-green-400: #59B179;
--dark-green-300: #82C49B;
--dark-green-200: #ACD8BC;
--dark-green-100: #DFEEE5;
--dark-green-50: #EAF5EE;
--gray-900: #192734;
--gray-800: #313B44;
--gray-700: #4C5A67;
--gray-600: #74808B;
--gray-500: #A6B1B9;
--gray-400: #C8CFD5;
--gray-300: #E2E6E9;
--gray-200: #EEF0F2;
--gray-100: #F4F5F6;
--gray-50: #F9FAFA;
--red-900: #631D1D;
--red-800: #802121;
--red-700: #9B2C2C;
--red-600: #C53030;
--red-500: #E24C4C;
--red-400: #EC645E;
--red-300: #FCA4A4;
--red-200: #FCC8C8;
--red-100: #FFECEC;
--red-50 : #FFF5F5;
--yellow-900: #5F370E;
--yellow-800: #744210;
--yellow-700: #975A16;
--yellow-600: #B7791F;
--yellow-500: #D69E2E;
--yellow-400: #ECB64B;
--yellow-300: #F6C35E;
--yellow-200: #FAD489;
--yellow-100: #FEE9BF;
--yellow-50: #FEF4E2;
--orange-900: #653019;
--orange-800: #7B3A1E;
--orange-700: #9C4621;
--orange-600: #CB5A2A;
--orange-500: #F8814F;
--orange-400: #F9966C;
--orange-300: #FDAE8C;
--orange-200: #FECDB8;
--orange-100: #FFEAE1;
--orange-50: #FFF5F0;
--purple-900: #343360;
--purple-800: #45438F;
--purple-700: #4946BF;
--purple-600: #6461D6;
--purple-500: #8684FF;
--purple-400: #9897F7;
--purple-300: #B9B8FA;
--purple-200: #DAD9F7;
--purple-100: #EAEAFB;
--purple-50: #F2F2FD;
--padding-xs: 5px;
--padding-sm: 10px;
--padding-md: 15px;
--padding-lg: 20px;
--padding-xl: 30px;
--padding-2xl: 40px;
--margin-xs: 5px;
--margin-sm: 8px;
--margin-md: 15px;
--margin-lg: 20px;
--margin-xl: 30px;
--margin-2xl: 40px;
--text-xs: 11px;
--text-sm: 12px;
--text-md: 13px;
--text-base: 14px;
--text-lg: 16px;
--text-xl: 18px;
--text-2xl: 20px;
--text-3xl: 22px;
--font-stack: "-apple-system", "BlinkMacSystemFont","Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell","Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
--navbar-height: 60px;
--text-bold: 500;
// --shadow-xs: 0px 0px 0.5px rgba(0,0,0,0.75), 0px 1px 2px rgba(0,0,0,0.13);
--shadow-xs: rgba(0, 0, 0, 0.05) 0px 0.5px 0px 0px, rgba(0, 0, 0, 0.08) 0px 0px 0px 1px, rgba(0, 0, 0, 0.05) 0px 2px 4px 0px;
--shadow-sm: 0px 1px 2px rgba(25, 39, 52, 0.05), 0px 0px 4px rgba(25, 39, 52, 0.1);
--shadow-base: 0px 4px 8px rgba(25, 39, 52, 0.06), 0px 0px 4px rgba(25, 39, 52, 0.12);
--shadow-md: 0px 8px 14px rgba(25, 39, 52, 0.08), 0px 2px 6px rgba(25, 39, 52, 0.04);
--shadow-lg: 0px 18px 22px rgba(25, 39, 52, 0.1), 0px 1px 10px rgba(0, 0, 0, 0.06), 0px 0.5px 5px rgba(25, 39, 52, 0.04);
--modal-shadow: var(--shadow-md);
--card-shadow: var(--shadow-sm);
--btn-shadow: var(--shadow-xs);
// Type Colors
--text-muted: var(--gray-600);
--text-light: var(--gray-700);
--text-color: var(--gray-900);
--heading-color: var(--gray-900);
// SVG Colors
--icon-fill: transparent;
--icon-fill-bg: var(--fg-color);
--icon-stroke: var(--gray-900);
// Layout Colors
--bg-color: var(--gray-50);
--fg-color: white;
--fg-hover-color: var(--gray-100);
--card-bg: var(--fg-color);
--control-bg: var(--gray-100);
--awesomebar-focus-bg: var(--fg-color);
--modal-bg: white;
--toast-bg: var(--modal-bg);
--popover-bg: white;
// Background Text Color Pairs
--bg-blue: var(--blue-50);
--bg-green: var(--dark-green-50);
--bg-yellow: var(--yellow-50);
--bg-orange: var(--orange-50);
--bg-red: var(--red-50);
--bg-gray: var(--gray-200);
--bg-light-gray: var(--gray-100);
--text-on-blue: var(--blue-600);
--text-on-green: var(--dark-green-500);
--text-on-yellow: var(--yellow-500);
--text-on-orange: var(--orange-500);
--text-on-red: var(--red-500);
--text-on-gray: var(--gray-600);
--text-on-light-gray: var(--gray-800);
// Other Colors
--sidebar-select-color: var(--gray-200);
--shadow-inset: inset 0px -1px 0px var(--gray-300);
--border-color: var(--gray-100);
--dark-border-color: var(--gray-300);
--highlight-color: var(--gray-50);
--yellow-highlight-color: var(--yellow-50);
// Border Sizes
--border-radius-sm: 4px;
--border-radius: 6px;
--border-radius-md: 8px;
--border-radius-lg: 12px;
--border-radius-full: 999px;
--checkbox-right-margin: var(--margin-xs);
--base-checkbox-size: 14px;
--custom-checkbox-size: 14px;
--primary-color: #2490EF;
--appreciation-color: var(--dark-green-600);
--appreciation-bg: var(--dark-green-100);
--criticism-color: var(--red-600);
--criticism-bg: var(--red-100);
}

View file

@ -1,4 +1,5 @@
@import "variables";
@import "css-variables";
@import "mixins";
@import "~bootstrap/scss/bootstrap";

View file

@ -38,6 +38,13 @@
max-height: 600px;
}
.print-format {
.ql-snow .ql-editor {
height: auto;
min-height: 0;
}
}
.ql-snow .ql-picker {
font-size: var(--text-sm);
}

View file

@ -1,3 +1,8 @@
html, body {
font-size: 16px;
}
// colors
$gray-900: #192734;
$gray-800: #313B44;
$gray-700: #4C5A67;
@ -18,218 +23,6 @@ $primary-light: lighten($primary, 42%) !default;
$card-box-shadow: 0px 0px 1px rgba(17, 43, 66, 0.16), 0px 1px 3px rgba(17, 43, 66, 0.1);
:root {
--pink-900: #5B1E34;
--pink-800: #702440;
--pink-700: #97264F;
--pink-600: #D2326D;
--pink-500: #F2508B;
--pink-400: #F46B9E;
--pink-300: #F584AE;
--pink-200: #FAB9D1;
--pink-100: #FCDCE8;
--pink-50 : #FEEDF3;
--blue-900: #1A4469;
--blue-800: #154875;
--blue-700: #1366AE;
--blue-600: #1579D0;
--blue-500: #2490EF;
--blue-400: #50A6F2;
--blue-300: #7CBCF5;
--blue-200: #A7D3F9;
--blue-100: #D3E9FC;
--blue-50 : #F0F8FE;
--green-900: #2D401D;
--green-800: #44622A;
--green-700: #518B21;
--green-600: #68AB30;
--green-500: #8CCF54;
--green-400: #A5D97A;
--green-300: #BCE39B;
--green-200: #D2ECBD;
--green-100: #E9F6DE;
--green-50 : #F4FAEE;
--dark-green-900: #1F3E2B;
--dark-green-800: #29593B;
--dark-green-700: #286840;
--dark-green-600: #2E844E;
--dark-green-500: #2F9D58;
--dark-green-400: #59B179;
--dark-green-300: #82C49B;
--dark-green-200: #ACD8BC;
--dark-green-100: #DFEEE5;
--dark-green-50: #EAF5EE;
--gray-900: #{$gray-900};
--gray-800: #{$gray-800};
--gray-700: #{$gray-700};
--gray-600: #{$gray-600};
--gray-500: #{$gray-500};
--gray-400: #{$gray-400};
--gray-300: #{$gray-300};
--gray-200: #{$gray-200};
--gray-100: #{$gray-100};
--gray-50: #{$gray-50};
--red-900: #631D1D;
--red-800: #802121;
--red-700: #9B2C2C;
--red-600: #C53030;
--red-500: #E24C4C;
--red-400: #EC645E;
--red-300: #FCA4A4;
--red-200: #FCC8C8;
--red-100: #FFECEC;
--red-50 : #FFF5F5;
--yellow-900: #5F370E;
--yellow-800: #744210;
--yellow-700: #975A16;
--yellow-600: #B7791F;
--yellow-500: #D69E2E;
--yellow-400: #ECB64B;
--yellow-300: #F6C35E;
--yellow-200: #FAD489;
--yellow-100: #FEE9BF;
--yellow-50: #FEF4E2;
--orange-900: #653019;
--orange-800: #7B3A1E;
--orange-700: #9C4621;
--orange-600: #CB5A2A;
--orange-500: #F8814F;
--orange-400: #F9966C;
--orange-300: #FDAE8C;
--orange-200: #FECDB8;
--orange-100: #FFEAE1;
--orange-50: #FFF5F0;
--purple-900: #343360;
--purple-800: #45438F;
--purple-700: #4946BF;
--purple-600: #6461D6;
--purple-500: #8684FF;
--purple-400: #9897F7;
--purple-300: #B9B8FA;
--purple-200: #DAD9F7;
--purple-100: #EAEAFB;
--purple-50: #F2F2FD;
--padding-xs: 5px;
--padding-sm: 10px;
--padding-md: 15px;
--padding-lg: 20px;
--padding-xl: 30px;
--padding-2xl: 40px;
--margin-xs: 5px;
--margin-sm: 8px;
--margin-md: 15px;
--margin-lg: 20px;
--margin-xl: 30px;
--margin-2xl: 40px;
--text-xs: 11px;
--text-sm: 12px;
--text-md: 13px;
--text-base: 14px;
--text-lg: 16px;
--text-xl: 18px;
--text-2xl: 20px;
--text-3xl: 22px;
--font-stack: "-apple-system", "BlinkMacSystemFont","Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell","Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
--navbar-height: 60px;
--text-bold: 500;
// --shadow-xs: 0px 0px 0.5px rgba(0,0,0,0.75), 0px 1px 2px rgba(0,0,0,0.13);
--shadow-xs: rgba(0, 0, 0, 0.05) 0px 0.5px 0px 0px, rgba(0, 0, 0, 0.08) 0px 0px 0px 1px, rgba(0, 0, 0, 0.05) 0px 2px 4px 0px;
--shadow-sm: 0px 1px 2px rgba(25, 39, 52, 0.05), 0px 0px 4px rgba(25, 39, 52, 0.1);
--shadow-base: 0px 4px 8px rgba(25, 39, 52, 0.06), 0px 0px 4px rgba(25, 39, 52, 0.12);
--shadow-md: 0px 8px 14px rgba(25, 39, 52, 0.08), 0px 2px 6px rgba(25, 39, 52, 0.04);
--shadow-lg: 0px 18px 22px rgba(25, 39, 52, 0.1), 0px 1px 10px rgba(0, 0, 0, 0.06), 0px 0.5px 5px rgba(25, 39, 52, 0.04);
--modal-shadow: var(--shadow-md);
--card-shadow: var(--shadow-sm);
--btn-shadow: var(--shadow-xs);
// Type Colors
--text-muted: var(--gray-600);
--text-light: var(--gray-700);
--text-color: var(--gray-900);
--heading-color: var(--gray-900);
// SVG Colors
--icon-fill: transparent;
--icon-fill-bg: var(--fg-color);
--icon-stroke: var(--gray-900);
// Layout Colors
--bg-color: var(--gray-50);
--fg-color: white;
--fg-hover-color: var(--gray-100);
--card-bg: var(--fg-color);
--control-bg: var(--gray-100);
--awesomebar-focus-bg: var(--fg-color);
--modal-bg: white;
--toast-bg: var(--modal-bg);
--popover-bg: white;
// Background Text Color Pairs
--bg-blue: var(--blue-50);
--bg-green: var(--dark-green-50);
--bg-yellow: var(--yellow-50);
--bg-orange: var(--orange-50);
--bg-red: var(--red-50);
--bg-gray: var(--gray-200);
--bg-light-gray: var(--gray-100);
--text-on-blue: var(--blue-600);
--text-on-green: var(--dark-green-500);
--text-on-yellow: var(--yellow-500);
--text-on-orange: var(--orange-500);
--text-on-red: var(--red-500);
--text-on-gray: var(--gray-600);
--text-on-light-gray: var(--gray-800);
// Other Colors
--sidebar-select-color: var(--gray-200);
--shadow-inset: inset 0px -1px 0px var(--gray-300);
--border-color: var(--gray-100);
--dark-border-color: var(--gray-300);
--highlight-color: var(--gray-50);
--yellow-highlight-color: var(--yellow-50);
// Border Sizes
--border-radius-sm: 4px;
--border-radius: 6px;
--border-radius-md: 8px;
--border-radius-lg: 12px;
--border-radius-full: 999px;
--checkbox-right-margin: var(--margin-xs);
--base-checkbox-size: 14px;
--custom-checkbox-size: 14px;
--primary-color: #{$primary};
--appreciation-color: var(--dark-green-600);
--appreciation-bg: var(--dark-green-100);
--criticism-color: var(--red-600);
--criticism-bg: var(--red-100);
}
html, body {
font-size: 16px;
}
$border-color: var(--border-color);
$code-color: var(--purple-600);
@ -338,3 +131,4 @@ $grid-breakpoints: (
@import '~bootstrap/scss/functions';
@import '~bootstrap/scss/variables';
@import "~bootstrap/scss/mixins";
@import 'css-variables';

View file

@ -1,137 +1,13 @@
@import "~bootstrap/scss/bootstrap";
// @import "~bootstrap/scss/bootstrap";
@import './desk/quill';
.col-xs-1 { @extend .col-md-1; }
.col-xs-2 { @extend .col-md-2; }
.col-xs-3 { @extend .col-3; }
.col-xs-4 { @extend .col-4; }
.col-xs-5 { @extend .col-md-5; }
.col-xs-6 { @extend .col-6; }
.col-xs-7 { @extend .col-7; }
.col-xs-8 { @extend .col-8; }
.col-xs-9 { @extend .col-9; }
.col-xs-10 { @extend .col-10; }
.col-xs-11 { @extend .col-11; }
.col-xs-12 { @extend .col-12; }
// @media print {
// *,
// *:before,
// *:after {
// color: #000;
// background: transparent;
// text-shadow: none !important;
// -webkit-box-shadow: none !important;
// box-shadow: none !important;
// }
// a,
// a:visited {
// text-decoration: underline;
// }
// abbr[title]:after {
// content: " (" attr(title) ")";
// }
// a[href^="#"]:after,
// a[href^="javascript:"]:after {
// content: "";
// }
// pre,
// blockquote {
// border: 1px solid #999;
// page-break-inside: avoid;
// }
// thead {
// display: table-header-group;
// }
// tr,
// img {
// page-break-inside: avoid;
// }
// img {
// max-width: 100% !important;
// }
// p,
// h2,
// h3 {
// orphans: 3;
// widows: 3;
// }
// h2,
// h3 {
// page-break-after: avoid;
// }
// select {
// background: #fff !important;
// }
// .navbar {
// display: none;
// }
// .btn > .caret,
// .dropup > .btn > .caret {
// border-top-color: #000 !important;
// }
// .label {
// border: 1px solid #000;
// }
// .table {
// border-collapse: collapse !important;
// }
// .table td,
// .table th {
// background-color: #fff;
// }
// .table-bordered th,
// .table-bordered td {
// border: 1px solid #ddd;
// }
// }
@import "./desk/css-variables";
// .visible-print {
// display: none !important;
// }
// @media print {
// .visible-print {
// display: block !important;
// }
// table.visible-print {
// display: table;
// }
// tr.visible-print {
// display: table-row !important;
// }
// th.visible-print,
// td.visible-print {
// display: table-cell !important;
// }
// }
// .visible-print-block {
// display: none !important;
// }
// @media print {
// .visible-print-block {
// display: block !important;
// }
// }
// .visible-print-inline {
// display: none !important;
// }
// @media print {
// .visible-print-inline {
// display: inline !important;
// }
// }
// .visible-print-inline-block {
// display: none !important;
// }
// @media print {
// .visible-print-inline-block {
// display: inline-block !important;
// }
// }
// @media print {
// .hidden-print {
// display: none !important;
// }
// }
// .print-format {
// .ql-snow .ql-editor {
// height: auto;
// min-height: 0;
// // max-height: 0;
// }
// }

View file

@ -26,7 +26,7 @@
<h4 class='col-sm-12'>{{ _(section.label) }}</h4>
{%- endif -%}
{% for column in section.columns %}
<div class="col-{{ (12 / section.columns|len)|int }} column-break">
<div class="col-xs-{{ (12 / section.columns|len)|int }} column-break">
{% for df in column.fields %}
{{ render_field(df, doc) }}
{% endfor %}

View file

@ -164,8 +164,9 @@ data-fieldname="{{ df.fieldname }}" data-fieldtype="{{ df.fieldtype }}"
{{ frappe.render_template(doc.print_heading_template, {"doc":doc}) }}
{% else %}
<div class="print-heading">
<h2>{{ doc.select_print_heading or (doc.print_heading if doc.print_heading != None
else _(doc.doctype)) }}<br>
<h2>
<div>{{ doc.select_print_heading or (doc.print_heading if doc.print_heading != None
else _(doc.doctype)) }}</div>
<small class="sub-heading">{{ doc.sub_heading if doc.sub_heading != None
else doc.name }}</small>
</h2>

View file

@ -74,6 +74,7 @@
}
.table {
font-size: inherit;
margin: 20px 0px;
}