Merge branch 'develop' of https://github.com/frappe/frappe into develop

This commit is contained in:
Achilles Rasquinha 2018-02-28 19:13:05 +05:30
commit 71cdff1e8e
12 changed files with 264 additions and 105 deletions

View file

@ -1,5 +1,6 @@
from __future__ import unicode_literals
import functools
import frappe
@frappe.whitelist()
@ -20,4 +21,4 @@ def get_help_messages():
for fn in frappe.get_hooks('get_help_messages'):
messages += frappe.get_attr(fn)()
return sorted(messages, lambda a, b: cmp(a.get('count'), b.get('count')))
return sorted(messages, key = functools.cmp_to_key(lambda a, b: cmp(a.get('count'), b.get('count'))))

View file

@ -166,6 +166,10 @@ frappe.activity.render_heatmap = function(page) {
}
frappe.views.Activity = class Activity extends frappe.views.BaseList {
constructor(opts) {
super(opts);
this.show();
}
setup_defaults() {
super.setup_defaults();

View file

@ -11,7 +11,7 @@ app_color = "orange"
source_link = "https://github.com/frappe/frappe"
app_license = "MIT"
develop_version = '10.x.x-develop'
develop_version = '11.x.x-develop'
app_email = "info@frappe.io"

View file

@ -234,7 +234,7 @@ frappe.ui.form.Grid = Class.extend({
this.wrapper.find(".grid-footer").toggle(true);
// show, hide buttons to add rows
if(this.cannot_add_rows) {
if(this.cannot_add_rows || (this.df && this.df.cannot_add_rows)) {
// add 'hide' to buttons
this.wrapper.find(".grid-add-row, .grid-add-multiple-rows")
.addClass('hide');

View file

@ -3,7 +3,6 @@ frappe.provide('frappe.views');
frappe.views.BaseList = class BaseList {
constructor(opts) {
Object.assign(this, opts);
this.show();
}
show() {
@ -152,6 +151,7 @@ frappe.views.BaseList = class BaseList {
}
set_menu_items() {
this.page.clear_menu();
const $secondary_action = this.page.set_secondary_action(
this.secondary_action.label,
this.secondary_action.action,

View file

@ -15,6 +15,11 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
return false;
}
constructor(opts) {
super(opts);
this.show();
}
show() {
this.init().then(() => {
if (frappe.route_options) {

View file

@ -154,23 +154,27 @@ $.extend(frappe.model, {
},
with_doc: function(doctype, name, callback) {
if(!name) name = doctype; // single type
if(locals[doctype] && locals[doctype][name] && frappe.model.get_docinfo(doctype, name)) {
callback(name);
} else {
return frappe.call({
method: 'frappe.desk.form.load.getdoc',
type: "GET",
args: {
doctype: doctype,
name: name
},
freeze: true,
callback: function(r) {
callback && callback(name, r);
}
});
}
return new Promise(resolve => {
if(!name) name = doctype; // single type
if(locals[doctype] && locals[doctype][name] && frappe.model.get_docinfo(doctype, name)) {
callback && callback(name);
resolve(frappe.get_doc(doctype, name));
} else {
return frappe.call({
method: 'frappe.desk.form.load.getdoc',
type: "GET",
args: {
doctype: doctype,
name: name
},
freeze: true,
callback: function(r) {
callback && callback(name, r);
resolve(frappe.get_doc(doctype, name));
}
});
}
});
},
get_docinfo: function(doctype, name) {

View file

@ -19,25 +19,24 @@ frappe.standard_pages["query-report"] = function() {
});
$(wrapper).bind("show", function() {
frappe.query_report.init();
frappe.query_report.show();
});
};
frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
show() {
this.init().then(() => this.load());
}
init() {
if (this.init_promise && frappe.get_route()[1] === this.report_name) {
if (this.init_promise) {
return this.init_promise;
}
let tasks = [
this.setup_defaults,
this.setup_page,
this.setup_report_wrapper,
this.setup_report
this.setup_report_wrapper
].map(fn => fn.bind(this));
this.init_promise = frappe.run_serially(tasks);
@ -47,17 +46,6 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
setup_defaults() {
this.route = frappe.get_route();
this.page_name = frappe.get_route_str();
this.report_name = this.route[1];
this.page_title = __(this.report_name);
this.user_settings = frappe.get_user_settings(this.report_name);
this.start = 0;
this.page_length = 20;
this.data = [];
this.fields = [];
this.filters = [];
this.order_by = 'modified desc';
// Setup buttons
this.primary_action = null;
@ -66,43 +54,58 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
action: () => this.refresh()
};
// throttle refresh for 300ms
this.refresh = frappe.utils.throttle(this.refresh, 300);
this.menu_items = [];
}
load() {
this.toggle_freeze(true);
if (this.report_name !== frappe.get_route()[1]) {
// different report
this.load_report();
} else {
// same report
this.refresh_report();
}
}
load_report() {
this.route = frappe.get_route();
this.page_name = frappe.get_route_str();
this.report_name = this.route[1];
this.page_title = __(this.report_name);
this.user_settings = frappe.get_user_settings(this.report_name);
this.menu_items = this.get_menu_items();
this.datatable = null;
// throttle refresh for 500ms
this.refresh = frappe.utils.throttle(this.refresh, 500);
frappe.run_serially([
() => this.get_report_doc(),
() => this.get_report_settings(),
() => this.report_settings.onload && this.report_settings.onload(this),
() => this.setup_page_head(),
() => this.refresh_report()
]);
}
// Report Doc
return frappe.db.get_doc('Report', this.report_name)
refresh_report() {
return frappe.run_serially([
() => this.setup_filters(),
() => this.set_route_filters(),
() => this.refresh()
]);
}
get_report_doc() {
return frappe.model.with_doc('Report', this.report_name)
.then(doc => {
this.report_doc = doc;
})
// Ref DocType
.then(() => {
if (this.report_doc.ref_doctype) {
return frappe.model.with_doctype(this.report_doc.ref_doctype);
}
return Promise.resolve();
});
.then(() => frappe.model.with_doc('DocType', this.report_doc.ref_doctype));
}
setup_report_wrapper() {
if (this.$report) return;
this.$report = $('<div class="report-wrapper">').appendTo(this.page.main);
}
setup_page_head() {
super.setup_page_head();
this.page.set_title_sub(`<label class="label label-warning text-color">${__('Beta')}</label>`);
}
setup_report() {
this.$report.empty();
this.datatable = null;
return this.load_report_script()
.then(() => this.load_report());
}
load_report_script() {
get_report_settings() {
if (frappe.query_reports[this.report_name]) {
this.report_settings = frappe.query_reports[this.report_name];
return this._load_script;
@ -126,20 +129,6 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
return this._load_script;
}
load_report() {
this.page.clear_inner_toolbar();
this.setup_filters();
// this.toggle_expand_collapse_buttons(false);
// this.is_tree_report = false;
if (this.report_settings.onload) {
frappe.run_serially([
() => this.report_settings.onload(this),
() => this.refresh()
]);
}
}
setup_filters() {
this.clear_filters();
const { filters = [] } = this.report_settings;
@ -181,8 +170,6 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
// as they can be used in
// setting/triggering the filters
this.set_filters_by_name();
return this.set_route_filters();
}
set_filters_by_name() {
@ -217,27 +204,23 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
refresh() {
const filters = this.get_filter_values(true);
if (this.report_ajax) {
// abort previous request
this.report_ajax.abort();
}
this.report_ajax = frappe.call({
return new Promise(resolve => frappe.call({
method: "frappe.desk.query_report.run",
type: "GET",
args: {
report_name: this.report_name,
filters: filters
}
}).then(r => {
this.report_ajax = undefined;
},
callback: resolve
})).then(r => {
this.render_report(r.message);
});
}
render_report(data) {
this.toggle_freeze(false);
this._data = data.result;
this._columns = data.columns;
if (this.datatable) {
this.datatable.refresh(data.result);
return;
@ -339,11 +322,111 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
}
set_breadcrumbs() {
if (!this.report_doc.ref_doctype) return;
if (!this.report_doc || !this.report_doc.ref_doctype) return;
const ref_doctype = frappe.get_meta(this.report_doc.ref_doctype);
frappe.breadcrumbs.add(ref_doctype.module);
}
print_report(print_settings) {
frappe.render_grid({
template: this.html_format || null,
title: __(this.report_name),
print_settings: print_settings,
filters: this.get_filter_values(),
data: this.get_data_for_print(),
columns: this.get_columns_for_print(),
report: this
});
}
pdf_report(print_settings) {
const base_url = frappe.urllib.get_base_url();
const print_css = frappe.boot.print_css;
const landscape = print_settings.orientation == "Landscape";
const columns = this.columns;
let html;
if (this.html_format) {
const content = frappe.render(this.html_format, {
data: this.get_data_for_print(),
filters: this.get_filter_values(),
report: this,
});
//Render Report in HTML
html = frappe.render_template("print_template", {
title:__(this.report_name),
content: content,
base_url: base_url,
print_css: print_css,
print_settings: print_settings,
landscape: landscape,
columns: columns
});
} else {
const content = frappe.render_template("print_grid", {
title: __(this.report_name),
data: this.get_data_for_print(),
columns: columns
})
//Render Report in HTML
html = frappe.render_template("print_template", {
content: content,
title: __(this.report_name),
base_url: base_url,
print_css: print_css,
print_settings: print_settings,
landscape: landscape,
columns: columns
});
}
frappe.render_pdf(html, print_settings);
}
export_report() {
if (this.export_dialog) {
this.export_dialog.clear();
this.export_dialog.show();
return;
}
this.export_dialog = frappe.prompt({
label: __('Select File Format'),
fieldname: 'file_format',
fieldtype: 'Select',
options: ['Excel', 'CSV'],
default: 'Excel',
reqd: 1
}, ({ file_format }) => {
if (file_format === 'CSV') {
frappe.tools.downloadify(this.get_data_for_print(), null, this.report_name);
} else {
const filters = this.get_filter_values(true);
const args = {
cmd: 'frappe.desk.query_report.export_query',
report_name: this.report_name,
file_format_type: file_format,
filters: filters,
visible_idx: this.datatable.datamanager.getFilteredRowIndices(),
};
open_url_post(frappe.request.url, args);
}
}, __("Export Report: "+ this.report_name), __("Download"));
}
get_data_for_print() {
const indices = this.datatable.datamanager.getFilteredRowIndices();
return indices.map(i => this._data[i]);
}
get_columns_for_print() {
return this._columns || [];
}
get_menu_items() {
return [
{
@ -360,24 +443,30 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
{
label: __('Print'),
action: () => {
frappe.ui.get_print_settings(false, function(print_settings) {
this.print_report(print_settings);
}, this.report_doc.letter_head);
frappe.ui.get_print_settings(
false,
print_settings => this.print_report(print_settings),
this.report_doc.letter_head
);
},
condition: () => frappe.model.can_print(this.report_doc.ref_doctype),
standard: true
},
{
label: __('PDF'),
action: () => {
frappe.ui.get_print_settings(false, function(print_settings) {
this.pdf_report(print_settings);
}, this.report_doc.letter_head);
frappe.ui.get_print_settings(
false,
print_settings => this.pdf_report(print_settings),
this.report_doc.letter_head
);
},
condition: () => frappe.model.can_print(this.report_doc.ref_doctype),
standard: true
},
{
label: __('Export'),
action: () => this.make_export(),
action: () => this.export_report(),
standard: true
},
{
@ -401,4 +490,31 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
},
];
}
setup_page_head() {
super.setup_page_head();
this.page.set_title_sub(`<label class="label label-warning text-color">${__('Beta')}</label>`);
}
setup_report_wrapper() {
if (this.$report) return;
this.$report = $('<div class="report-wrapper">').appendTo(this.page.main);
this.$freeze =
$(`<div class="report-loading-area flex justify-center align-center text-muted" style="height: 50vh;">
<div>${__('Loading')}...</div>
</div>`).hide().appendTo(this.page.main);
}
toggle_freeze(flag) {
this.$freeze.toggle(flag);
this.$report.toggle(!flag);
}
get data() {
return this._data;
}
get columns() {
return this._columns;
}
};

View file

@ -104,7 +104,7 @@ frappe.render_grid = function(opts) {
// render content
if(!opts.content) {
opts.content = frappe.render_template("print_grid", opts);
opts.content = frappe.render_template(opts.template || "print_grid", opts);
}
// render HTML wrapper page
@ -135,3 +135,31 @@ frappe.render_tree = function(opts) {
w.document.write(tree);
w.document.close();
}
frappe.render_pdf = function(html, opts = {}) {
//Create a form to place the HTML content
var formData = new FormData();
//Push the HTML content into an element
formData.append("html", html);
if (opts.orientation) {
formData.append("orientation", opts.orientation);
}
var blob = new Blob([], { type: "text/xml"});
formData.append("blob", blob);
var xhr = new XMLHttpRequest();
xhr.open("POST", '/api/method/frappe.utils.print_format.report_to_pdf');
xhr.setRequestHeader("X-Frappe-CSRF-Token", frappe.csrf_token);
xhr.responseType = "arraybuffer";
xhr.onload = function(success) {
if (this.status === 200) {
var blob = new Blob([success.currentTarget.response], {type: "application/pdf"});
var objectUrl = URL.createObjectURL(blob);
//Open report in a new window
window.open(objectUrl);
}
};
xhr.send(formData);
}

View file

@ -128,7 +128,7 @@ def prepare_header_footer(soup):
# create temp file
fname = os.path.join("/tmp", "frappe-pdf-{0}.html".format(frappe.generate_hash()))
with open(fname, "w") as f:
with open(fname, "wb") as f:
f.write(html.encode("utf-8"))
# {"header-html": "/tmp/frappe-pdf-random.html"}

View file

@ -2,6 +2,7 @@
# MIT License. See license.txt
from __future__ import unicode_literals
import functools
import frappe, re, os
from six import iteritems
@ -257,8 +258,8 @@ def get_full_index(route=None, app=None):
added.append(child_route)
# add remaining pages not in index.txt
_children = sorted(children, lambda a, b: cmp(
os.path.basename(a.route), os.path.basename(b.route)))
_children = sorted(children, key = functools.cmp_to_key(lambda a, b: cmp(
os.path.basename(a.route), os.path.basename(b.route))))
for child_route in _children:
if child_route not in new_children:

View file

@ -612,7 +612,7 @@ forwarded@~0.1.2:
frappe-datatable@frappe/datatable:
version "0.0.2"
resolved "https://codeload.github.com/frappe/datatable/tar.gz/5b8be4c5b09a243ed8580cb9667d7658ca249f02"
resolved "https://codeload.github.com/frappe/datatable/tar.gz/99701f2477b3fb8180ccafaf2c2746886b13ba53"
dependencies:
clusterize.js "^0.18.0"
lodash "^4.17.5"