[print-format] add print heading + fix tables
This commit is contained in:
parent
4c8558665d
commit
c19cb66542
11 changed files with 149 additions and 57 deletions
|
|
@ -364,6 +364,29 @@ class BaseDocument(object):
|
|||
return format_value(self.get(fieldname), self.meta.get_field(fieldname),
|
||||
doc=doc or self, currency=currency)
|
||||
|
||||
def get_print_template(self, fieldname, parent_doc=None):
|
||||
"""Returns print template for given fieldname if specified in controller
|
||||
or parent controller.
|
||||
|
||||
Templates must be specified as:
|
||||
|
||||
class MyDocType(Document):
|
||||
def __setup__(self):
|
||||
self.print_templates = {
|
||||
"[fieldname]": "templates/includes/template_name.html",
|
||||
"[table fieldname].[fieldname]": "templates/includes/template_name.html"
|
||||
}
|
||||
|
||||
:param fieldname: Field for which template is queried.
|
||||
:param parent_doc: Parent Document, if child doc."""
|
||||
src = self
|
||||
if parent_doc:
|
||||
src = parent_doc
|
||||
fieldname = self.parentfield + "." + fieldname
|
||||
if hasattr(src, "print_templates"):
|
||||
return src.print_templates.get(fieldname)
|
||||
|
||||
|
||||
def _filter(data, filters, limit=None):
|
||||
"""pass filters as:
|
||||
{"key": "val", "key": ["!=", "val"],
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ class Meta(Document):
|
|||
|
||||
def is_print_hide(self, fieldname):
|
||||
df = self.get_field(fieldname)
|
||||
return df.get("__print_hide") or df.print_hide
|
||||
return df and (df.get("__print_hide") or df.print_hide)
|
||||
|
||||
doctype_table_fields = [
|
||||
frappe._dict({"fieldname": "fields", "options": "DocField"}),
|
||||
|
|
|
|||
|
|
@ -3,13 +3,16 @@
|
|||
margin: 0px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.print-format-builder-add-section {
|
||||
.print-format-builder-add-section, .print-format-builder-header {
|
||||
border: 1px dashed #d1d8dd;
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.print-format-builder-header {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.print-format-builder-column {
|
||||
padding: 15px;
|
||||
margin: 0px -15px 0 -16px;
|
||||
|
|
|
|||
|
|
@ -166,12 +166,19 @@ frappe.PrintFormatBuilder = Class.extend({
|
|||
.appendTo(this.page.main);
|
||||
this.setup_sortable();
|
||||
this.setup_add_section();
|
||||
this.setup_edit_heading();
|
||||
},
|
||||
prepare_data: function() {
|
||||
this.data = JSON.parse(this.print_format.format_data || "[]");
|
||||
if(!this.data.length) {
|
||||
// new layout
|
||||
this.data = this.meta.fields;
|
||||
} else {
|
||||
// extract print_heading_template if found
|
||||
if(this.data[0].fieldname==="print_heading_template") {
|
||||
this.print_heading_template = this.data[0].options;
|
||||
this.data = this.data.splice(1);
|
||||
}
|
||||
}
|
||||
this.layout_data = [];
|
||||
var section = null, column = null, me = this;
|
||||
|
|
@ -242,7 +249,7 @@ frappe.PrintFormatBuilder = Class.extend({
|
|||
!_f.print_hide && f.label) {
|
||||
|
||||
// column names set as fieldname|width
|
||||
f.visible_columns.push({fieldname: _f.fieldname, width: _f.width});
|
||||
f.visible_columns.push({fieldname: _f.fieldname, print_width: (_f.width || "")});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -412,6 +419,14 @@ frappe.PrintFormatBuilder = Class.extend({
|
|||
me.setup_sortable_for_column($section.find(".print-format-builder-column").get(0));
|
||||
});
|
||||
},
|
||||
setup_edit_heading: function() {
|
||||
var me = this;
|
||||
this.page.main.find(".edit-heading").on("click", function() {
|
||||
var $heading = $(this).parents(".print-format-builder-header:first")
|
||||
.find(".print-format-builder-print-heading");
|
||||
var d = me.get_edit_html_dialog(__("Edit Heading"), __("Heading"), $heading);
|
||||
})
|
||||
},
|
||||
setup_column_selector: function() {
|
||||
var me = this;
|
||||
this.page.main.on("click", ".select-columns", function() {
|
||||
|
|
@ -424,7 +439,7 @@ frappe.PrintFormatBuilder = Class.extend({
|
|||
|
||||
$.each(columns, function(i, v) {
|
||||
var parts = v.split("|");
|
||||
widths[parts[0]] = parts[1];
|
||||
widths[parts[0]] = parts[1] || "";
|
||||
});
|
||||
|
||||
var d = new frappe.ui.Dialog({
|
||||
|
|
@ -473,7 +488,7 @@ frappe.PrintFormatBuilder = Class.extend({
|
|||
});
|
||||
},
|
||||
get_visible_columns_string: function(f) {
|
||||
return $.map(f.visible_columns, function(v) { return v.fieldname + "|" + v.width }).join(",")
|
||||
return $.map(f.visible_columns, function(v) { return v.fieldname + "|" + (v.print_width || "") }).join(",")
|
||||
},
|
||||
get_no_content: function() {
|
||||
return '<div class="text-extra-muted" data-no-content>'+__("Edit to add content")+'</div>'
|
||||
|
|
@ -481,38 +496,48 @@ frappe.PrintFormatBuilder = Class.extend({
|
|||
setup_edit_custom_html: function() {
|
||||
var me = this;
|
||||
this.page.main.on("click", ".edit-html", function() {
|
||||
var parent = $(this).parents(".print-format-builder-field:first"),
|
||||
$content = parent.find(".html-content");
|
||||
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __("Edit Custom HTML"),
|
||||
me.get_edit_html_dialog(__("Edit Custom HTML"), __("Custom HTML"),
|
||||
$(this).parents(".print-format-builder-field:first").find(".html-content"));
|
||||
});
|
||||
},
|
||||
get_edit_html_dialog: function(title, label, $content) {
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: title,
|
||||
fields: [
|
||||
{
|
||||
fieldname: "content",
|
||||
fieldtype: "Text Editor",
|
||||
label: "Custom HTML"
|
||||
label: label
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
var content = $content.html();
|
||||
if(content.indexOf("data-no-content")!==-1) content = "";
|
||||
// set existing content in input
|
||||
content = $content.html();
|
||||
if(content.indexOf("data-no-content")!==-1) content = "";
|
||||
d.set_input("content", content);
|
||||
|
||||
d.set_input("content", content);
|
||||
|
||||
d.set_primary_action(__("Update"), function() {
|
||||
$content.html(d.get_value("content"));
|
||||
d.hide();
|
||||
});
|
||||
|
||||
d.show();
|
||||
|
||||
return false;
|
||||
d.set_primary_action(__("Update"), function() {
|
||||
$content.html(d.get_value("content"));
|
||||
d.hide();
|
||||
});
|
||||
|
||||
d.show();
|
||||
|
||||
return d;
|
||||
},
|
||||
save_print_format: function() {
|
||||
var data = [],
|
||||
me = this;
|
||||
|
||||
// add print heading as the first field
|
||||
// this will be removed and set as a doc property
|
||||
// before rendering
|
||||
data.push({"fieldname": "print_heading_template",
|
||||
fieldtype:"HTML",
|
||||
options: this.page.main.find(".print-format-builder-print-heading").html()});
|
||||
|
||||
// add pages
|
||||
this.page.main.find(".print-format-builder-section").each(function() {
|
||||
data.push({"fieldtype": "Section Break"});
|
||||
$(this).find(".print-format-builder-column").each(function() {
|
||||
|
|
@ -530,7 +555,7 @@ frappe.PrintFormatBuilder = Class.extend({
|
|||
$.each(columns, function(i, c) {
|
||||
var parts = c.split("|");
|
||||
df.visible_columns.push({fieldname:parts[0],
|
||||
width:parts[1]});
|
||||
print_width:parts[1]});
|
||||
});
|
||||
}
|
||||
if(fieldtype==="Custom HTML") {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<input class="form-control column-width input-sm text-right"
|
||||
value="{%= widths[f.fieldname] || "" %}"
|
||||
value="{%= (widths[f.fieldname] || "") %}"
|
||||
data-fieldname="{%= f.fieldname %}"
|
||||
style="width: 100px; display: inline"
|
||||
{%= selected ? "" : "disabled" %}>
|
||||
|
|
|
|||
|
|
@ -2,13 +2,23 @@
|
|||
<div class="text-muted text-center">
|
||||
{%= __("Drag elements from the sidebar to add. Drag them back to trash.") %}<br><br>
|
||||
</div>
|
||||
<div class="print-format-builder-header">
|
||||
<div class="text-right">
|
||||
<a class="edit-heading btn btn-default btn-xs">
|
||||
{%= __("Edit Heading") %}</a>
|
||||
</div>
|
||||
<div class="print-format-builder-print-heading">
|
||||
{%= me.print_heading_template || __("<span class=text-muted data-no-content=1>"
|
||||
+ __("Edit to set heading") + "</span>") %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="print-format-builder-layout">
|
||||
{% for(var i=0; i < data.length; i++) { %}
|
||||
{%= frappe.render_template("print_format_builder_section",
|
||||
{section: data[i], me:me}) %}
|
||||
{% } %}
|
||||
</div>
|
||||
<div class="print-format-builder-add-section text-muted">
|
||||
<div class="print-format-builder-add-section text-muted text-center">
|
||||
<span class="octicon octicon-plus"></span>
|
||||
<a class="grey">Add a new section</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ frappe.route_titles = {};
|
|||
frappe.route_history = [];
|
||||
frappe.view_factory = {};
|
||||
frappe.view_factories = [];
|
||||
frappe.route_options = {};
|
||||
frappe.route_options = null;
|
||||
|
||||
frappe.route = function() {
|
||||
if(frappe.re_route[window.location.hash]) {
|
||||
|
|
|
|||
|
|
@ -375,11 +375,8 @@ bsEditorToolbar = Class.extend({
|
|||
|
||||
// edit html
|
||||
this.toolbar.find(".btn-html").on("click", function() {
|
||||
if(!window.bs_html_editor)
|
||||
window.bs_html_editor = new bsHTMLEditor();
|
||||
|
||||
window.bs_html_editor.show(me.editor);
|
||||
})
|
||||
new bsHTMLEditor().show(me.editor);
|
||||
});
|
||||
},
|
||||
|
||||
update: function () {
|
||||
|
|
@ -457,10 +454,9 @@ bsHTMLEditor = Class.extend({
|
|||
var me = this;
|
||||
this.modal = bs_get_modal("<i class='icon-code'></i> Edit HTML", '<textarea class="form-control" \
|
||||
style="height: 400px; width: 100%; font-family: Monaco, \'Courier New\', monospace; font-size: 11px">\
|
||||
</textarea><br>\
|
||||
<button class="btn btn-primary" style="margin-top: 7px;">' + __("Save") + '</button>');
|
||||
this.modal.addClass("frappe-ignore-click");
|
||||
this.modal.find(".btn-primary").on("click", function() {
|
||||
</textarea>');
|
||||
this.modal.addClass("frappe-ignore-click");
|
||||
this.modal.find(".btn-primary").removeClass("hide").html(__("Update")).on("click", function() {
|
||||
me._html = me.modal.find("textarea").val();
|
||||
|
||||
$.each(me.editor.dataurls, function(key, val) {
|
||||
|
|
@ -476,7 +472,7 @@ bsHTMLEditor = Class.extend({
|
|||
show: function(editor) {
|
||||
var me = this;
|
||||
this.editor = editor;
|
||||
this.modal.modal("show")
|
||||
this.modal.modal("show");
|
||||
var html = me.editor.html();
|
||||
// pack dataurls so that html display is faster
|
||||
this.editor.dataurls = {}
|
||||
|
|
|
|||
|
|
@ -142,8 +142,22 @@ def get_print_format(doctype, print_format):
|
|||
frappe.TemplateNotFoundError)
|
||||
|
||||
def make_layout(doc, meta, format_data=None):
|
||||
"""Builds a hierarchical layout object from the fields list to be rendered
|
||||
by `standard.html`
|
||||
|
||||
:param doc: Document to be rendered.
|
||||
:param meta: Document meta object (doctype).
|
||||
:param format_data: Fields sequence and properties defined by Print Format Builder."""
|
||||
layout, page = [], []
|
||||
layout.append(page)
|
||||
|
||||
if format_data:
|
||||
# extract print_heading_template from the first field
|
||||
# and remove the field
|
||||
if format_data[0].get("fieldname") == "print_heading_template":
|
||||
doc.print_heading_template = format_data[0].get("options")
|
||||
format_data = format_data[1:]
|
||||
|
||||
for df in format_data or meta.fields:
|
||||
if format_data:
|
||||
# embellish df with original properties
|
||||
|
|
@ -234,11 +248,19 @@ def get_print_style(style=None):
|
|||
|
||||
return css
|
||||
|
||||
def get_visible_columns(data, table_meta):
|
||||
def get_visible_columns(data, table_meta, df):
|
||||
"""Returns list of visible columns based on print_hide and if all columns have value."""
|
||||
columns = []
|
||||
for tdf in table_meta.fields:
|
||||
if is_visible(tdf) and column_has_value(data, tdf.fieldname):
|
||||
columns.append(tdf)
|
||||
if df.get("visible_columns"):
|
||||
# columns specified by column builder
|
||||
for col_df in df.get("visible_columns"):
|
||||
newdf = table_meta.get_field(col_df.get("fieldname")).as_dict().copy()
|
||||
newdf.update(col_df)
|
||||
columns.append(newdf)
|
||||
else:
|
||||
for col_df in table_meta.fields:
|
||||
if is_visible(col_df) and column_has_value(data, col_df.get("fieldname")):
|
||||
columns.append(col_df)
|
||||
|
||||
return columns
|
||||
|
||||
|
|
|
|||
|
|
@ -13,13 +13,13 @@
|
|||
{%- macro render_table(df, doc) -%}
|
||||
{%- set table_meta = frappe.get_meta(df.options) -%}
|
||||
{%- set data = doc.get(df.fieldname)[df.start:df.end] -%}
|
||||
{%- if doc.table_print_templates and
|
||||
doc.table_print_templates.get(df.fieldname) -%}
|
||||
{% include doc.table_print_templates[df.fieldname] %}
|
||||
{%- if doc.print_templates and
|
||||
doc.print_templates.get(df.fieldname) -%}
|
||||
{% include doc.print_templates[df.fieldname] %}
|
||||
{%- else -%}
|
||||
{%- if data -%}
|
||||
{%- set visible_columns = get_visible_columns(doc.get(df.fieldname),
|
||||
table_meta) -%}
|
||||
table_meta, df) -%}
|
||||
<div>
|
||||
<table class="table table-bordered table-condensed">
|
||||
<thead>
|
||||
|
|
@ -36,7 +36,8 @@
|
|||
<tr>
|
||||
<td>{{ d.idx }}</td>
|
||||
{% for tdf in visible_columns %}
|
||||
<td class="{{ get_align_class(tdf.fieldtype) }}">{{ print_value(tdf, d, doc) }}</td>
|
||||
<td class="{{ get_align_class(tdf.fieldtype) }}">
|
||||
{{ print_value(tdf, d, doc) }}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
@ -76,10 +77,14 @@
|
|||
{%- endmacro -%}
|
||||
|
||||
{%- macro print_value(df, doc, parent_doc=None) -%}
|
||||
{% if df.fieldtype=="Check" %}
|
||||
{% if doc.get_print_template(df.fieldname, parent_doc) %}
|
||||
{% include doc.get_print_template(df.fieldname, parent_doc) %}
|
||||
{% elif df.fieldtype=="Check" %}
|
||||
<i class="{{ 'icon-check' if doc[df.fieldname] else 'icon-check-empty' }}"></i>
|
||||
{% elif df.fieldtype=="Image" %}
|
||||
<img src="{{ doc[doc.meta.get_field(df.fieldname).options] }}" class="img-responsive">
|
||||
{% elif df.fieldtype=="HTML" %}
|
||||
{{ frappe.render_template(df.options, {"doc":doc}) }}
|
||||
{% else %}
|
||||
{{ doc.get_formatted(df.fieldname, parent_doc or doc) }}
|
||||
{% endif %}
|
||||
|
|
@ -101,19 +106,26 @@
|
|||
{% if letter_head and not no_letterhead %}
|
||||
<div class="letter-head">{{ letter_head }}</div>
|
||||
{% endif %}
|
||||
<div class="print-heading">
|
||||
<h3>{{ doc.select_print_heading or (doc.print_heading if doc.print_heading != None
|
||||
else _(doc.doctype)) }}</h3>
|
||||
<h4 class="text-muted">{{ doc.sub_heading if doc.sub_heading != None
|
||||
else ("#" + doc[doc.meta.title_field or "name"]) }}</h4>
|
||||
</div>
|
||||
{% if doc.print_heading_template %}
|
||||
{{ 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)) }}
|
||||
<small>{{ doc.sub_heading if doc.sub_heading != None
|
||||
else doc.name }}</small>
|
||||
</h2>
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- if doc.meta.is_submittable and doc.docstatus==0-%}
|
||||
<div class="text-center">
|
||||
<h4 style="margin: 0px;">{{ _("DRAFT") }}</h4></div>
|
||||
<h4 style="margin: 0px;">{{ _("DRAFT") }}</h4>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if doc.meta.is_submittable and doc.docstatus==2-%}
|
||||
<div class="text-center">
|
||||
<h4 style="margin: 0px;">{{ _("CANCELLED") }}</h4></div>
|
||||
<h4 style="margin: 0px;">{{ _("CANCELLED") }}</h4>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{% if max_pages > 1 %}
|
||||
<p class="text-right">{{ _("Page #{0} of {1}").format(page_num, max_pages) }}</p>
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ def get_allowed_functions_for_jenv():
|
|||
"date_format": frappe.db.get_default("date_format") or "yyyy-mm-dd",
|
||||
"get_fullname": frappe.utils.get_fullname,
|
||||
"get_gravatar": frappe.utils.get_gravatar,
|
||||
"full_name": hasattr(frappe.local, "session") and frappe.local.session.data.full_name or "Guest"
|
||||
"full_name": hasattr(frappe.local, "session") and frappe.local.session.data.full_name or "Guest",
|
||||
"render_template": frappe.render_template
|
||||
},
|
||||
"autodoc": {
|
||||
"get_version": get_version,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue