Merge branch 'staging' into develop
This commit is contained in:
commit
e551153ea0
19 changed files with 324 additions and 109 deletions
|
|
@ -17,7 +17,7 @@ from faker import Faker
|
|||
from .exceptions import *
|
||||
from .utils.jinja import (get_jenv, get_template, render_template, get_email_from_template, get_jloader)
|
||||
|
||||
__version__ = '10.1.48'
|
||||
__version__ = '10.1.49'
|
||||
__title__ = "Frappe Framework"
|
||||
|
||||
local = Local()
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ frappe.ui.form.on('Data Import', {
|
|||
};
|
||||
});
|
||||
|
||||
// should never check public
|
||||
frm.fields_dict["import_file"].df.is_private = 1;
|
||||
|
||||
frappe.realtime.on("data_import_progress", function(data) {
|
||||
if (data.data_import === frm.doc.name) {
|
||||
if (data.reload && data.reload === true) {
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ class Report(Document):
|
|||
return True
|
||||
|
||||
def update_report_json(self):
|
||||
if not self.json:
|
||||
self.json = '{}'
|
||||
|
||||
if self.json:
|
||||
data = json.loads(self.json)
|
||||
data["add_total_row"] = self.add_total_row
|
||||
|
|
@ -121,7 +124,15 @@ class Report(Document):
|
|||
else:
|
||||
# standard report
|
||||
params = json.loads(self.json)
|
||||
columns = params.get('columns')
|
||||
|
||||
if params.get('columns'):
|
||||
columns = params.get('columns')
|
||||
else:
|
||||
columns = [['name', self.ref_doctype]]
|
||||
for df in frappe.get_meta(self.ref_doctype).fields:
|
||||
if df.in_list_view:
|
||||
columns.append([df.fieldname, self.ref_doctype])
|
||||
|
||||
_filters = params.get('filters') or []
|
||||
|
||||
if filters:
|
||||
|
|
@ -135,7 +146,11 @@ class Report(Document):
|
|||
# sort by is saved as DocType.fieldname, covert it to sql
|
||||
return '`tab{0}`.`{1}`'.format(*parts)
|
||||
|
||||
order_by = _format(params.get('sort_by').split('.')) + ' ' + params.get('sort_order')
|
||||
if params.get('sort_by'):
|
||||
order_by = _format(params.get('sort_by').split('.')) + ' ' + params.get('sort_order')
|
||||
else:
|
||||
order_by = _format(self.ref_doctype, 'modified') + ' desc'
|
||||
|
||||
if params.get('sort_by_next'):
|
||||
order_by += ', ' + _format(params.get('sort_by_next').split('.')) + ' ' + params.get('sort_order_next')
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -40,10 +41,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -69,10 +72,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -99,10 +104,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -129,10 +136,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -158,10 +167,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -188,10 +199,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -218,10 +231,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -247,10 +262,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -277,10 +294,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -307,10 +326,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -337,16 +358,18 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "data",
|
||||
"fieldtype": "Text",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
|
|
@ -367,10 +390,12 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
|
|
@ -397,6 +422,7 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
|
|
@ -410,7 +436,7 @@
|
|||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-02-06 11:56:43.519455",
|
||||
"modified": "2018-09-21 08:49:07.915376",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Transaction Log",
|
||||
|
|
@ -419,7 +445,6 @@
|
|||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
|
@ -445,5 +470,6 @@
|
|||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ class TransactionLog(Document):
|
|||
if prev_hash:
|
||||
self.previous_hash = prev_hash[0][0]
|
||||
else:
|
||||
self.previous_hash = _("Indexing broken")
|
||||
self.previous_hash = "Indexing broken"
|
||||
else:
|
||||
self.previous_hash = self.hash_line()
|
||||
self.transaction_hash = self.hash_line()
|
||||
|
|
|
|||
|
|
@ -59,11 +59,11 @@ def generate_report_result(report, filters=None, user=None):
|
|||
method_name = get_report_module_dotted_path(module, report.name) + ".execute"
|
||||
threshold = 10
|
||||
res = []
|
||||
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
# The JOB
|
||||
res = frappe.get_attr(method_name)(frappe._dict(filters))
|
||||
|
||||
|
||||
end_time = datetime.datetime.now()
|
||||
|
||||
if (end_time - start_time).seconds > threshold and not report.prepared_report:
|
||||
|
|
@ -159,6 +159,8 @@ def run(report_name, filters=None, user=None):
|
|||
frappe.msgprint(_("Must have report permission to access this report."),
|
||||
raise_exception=True)
|
||||
|
||||
result = None
|
||||
|
||||
if report.prepared_report:
|
||||
if filters:
|
||||
if isinstance(filters, string_types):
|
||||
|
|
@ -167,9 +169,13 @@ def run(report_name, filters=None, user=None):
|
|||
dn = filters.get("prepared_report_name")
|
||||
else:
|
||||
dn = ""
|
||||
return get_prepared_report_result(report, filters, dn)
|
||||
result = get_prepared_report_result(report, filters, dn)
|
||||
else:
|
||||
return generate_report_result(report, filters, user)
|
||||
result = generate_report_result(report, filters, user)
|
||||
|
||||
result["add_total_row"] = report.add_total_row
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_prepared_report_result(report, filters, dn=""):
|
||||
|
|
|
|||
|
|
@ -165,9 +165,10 @@ def get_context(context):
|
|||
if not frappe.safe_eval(recipient.condition, None, context):
|
||||
continue
|
||||
if recipient.email_by_document_field:
|
||||
if validate_email_add(doc.get(recipient.email_by_document_field)):
|
||||
recipient.email_by_document_field = doc.get(recipient.email_by_document_field).replace(",", "\n")
|
||||
recipients = recipients + recipient.email_by_document_field.split("\n")
|
||||
email_ids_value = doc.get(recipient.email_by_document_field)
|
||||
if validate_email_add(email_ids_value):
|
||||
email_ids = email_ids_value.replace(",", "\n")
|
||||
recipients = recipients + email_ids.split("\n")
|
||||
|
||||
# else:
|
||||
# print "invalid email"
|
||||
|
|
|
|||
|
|
@ -88,6 +88,13 @@ def send(recipients=None, sender=None, subject=None, message=None, text_content=
|
|||
|
||||
recipients = [r for r in list(set(recipients)) if r and r not in unsubscribed]
|
||||
|
||||
if cc:
|
||||
cc = [r for r in list(set(cc)) if r and r not in unsubscribed]
|
||||
|
||||
if not recipients and not cc:
|
||||
# Recipients may have been unsubscribed, exit quietly
|
||||
return
|
||||
|
||||
email_text_context = text_content
|
||||
|
||||
should_append_unsubscribe = (add_unsubscribe_link
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ source_link = "https://github.com/frappe/frappe"
|
|||
app_license = "MIT"
|
||||
|
||||
develop_version = '11.x.x-develop'
|
||||
staging_version = '11.0.2'
|
||||
staging_version = '11.0.3'
|
||||
|
||||
app_email = "info@frappe.io"
|
||||
|
||||
|
|
@ -125,7 +125,10 @@ doc_events = {
|
|||
"frappe.desk.notifications.clear_doctype_notifications",
|
||||
"frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions"
|
||||
],
|
||||
"on_trash": "frappe.desk.notifications.clear_doctype_notifications",
|
||||
"on_trash": [
|
||||
"frappe.desk.notifications.clear_doctype_notifications",
|
||||
"frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions"
|
||||
],
|
||||
"on_change": [
|
||||
"frappe.core.doctype.feedback_trigger.feedback_trigger.trigger_feedback_request",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ def get_role_permissions(doctype_meta, user=None, verbose=False):
|
|||
def has_permission_without_if_owner_enabled(ptype):
|
||||
return any(p.get(ptype, 0) and not p.get('if_owner', 0) for p in applicable_permissions)
|
||||
|
||||
applicable_permissions = list(filter(is_perm_applicable, doctype_meta.permissions))
|
||||
applicable_permissions = list(filter(is_perm_applicable, getattr(doctype_meta, 'permissions', [])))
|
||||
has_if_owner_enabled = any(p.get('if_owner', 0) for p in applicable_permissions)
|
||||
|
||||
for ptype in rights:
|
||||
|
|
|
|||
|
|
@ -305,38 +305,6 @@
|
|||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "enable_print_server",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Enable Print Server",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
|
|
@ -473,7 +441,7 @@
|
|||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.enable_print_server == 1",
|
||||
"depends_on": "",
|
||||
"fieldname": "server_printer",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
|
|
@ -499,6 +467,38 @@
|
|||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "enable_print_server",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Enable Print Server",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
|
|
@ -507,6 +507,7 @@
|
|||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "localhost",
|
||||
"depends_on": "enable_print_server",
|
||||
"fieldname": "server_ip",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
|
|
@ -539,6 +540,7 @@
|
|||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "enable_print_server",
|
||||
"fieldname": "printer_name",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
|
|
@ -564,37 +566,6 @@
|
|||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_17",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
|
|
@ -603,6 +574,7 @@
|
|||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "631",
|
||||
"depends_on": "enable_print_server",
|
||||
"fieldname": "port",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
|
|
@ -832,7 +804,7 @@
|
|||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-06-29 01:34:57.508272",
|
||||
"modified": "2018-09-20 12:10:14.440598",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Printing",
|
||||
"name": "Print Settings",
|
||||
|
|
|
|||
|
|
@ -495,7 +495,13 @@ frappe.ui.form.Layout = Class.extend({
|
|||
|
||||
var parent = this.frm ? this.frm.doc : null;
|
||||
|
||||
if(expression.substr(0,5)=='eval:') {
|
||||
if(typeof(expression) === 'boolean') {
|
||||
out = expression;
|
||||
|
||||
} else if(typeof(expression) === 'function') {
|
||||
out = expression(doc);
|
||||
|
||||
} else if(expression.substr(0,5)=='eval:') {
|
||||
try {
|
||||
out = eval(expression.substr(5));
|
||||
} catch(e) {
|
||||
|
|
|
|||
|
|
@ -265,6 +265,7 @@ frappe.ui.BaseList = Class.extend({
|
|||
|
||||
clear: function () {
|
||||
this.data = [];
|
||||
this.wrapper.find('.list-select-all').prop('checked', false);
|
||||
this.wrapper.find('.result-list').empty();
|
||||
this.wrapper.find('.result').show();
|
||||
this.wrapper.find('.no-result').hide();
|
||||
|
|
|
|||
|
|
@ -98,10 +98,17 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
|
|||
() => this.get_report_doc(),
|
||||
() => this.get_report_settings(),
|
||||
() => this.setup_page_head(),
|
||||
() => this.refresh_report()
|
||||
() => this.refresh_report(),
|
||||
() => this.add_make_chart_button()
|
||||
]);
|
||||
}
|
||||
|
||||
add_make_chart_button(){
|
||||
this.page.add_inner_button(__("Set Chart"), () => {
|
||||
this.get_possible_chart_options();
|
||||
});
|
||||
}
|
||||
|
||||
refresh_report() {
|
||||
this.toggle_message(true);
|
||||
|
||||
|
|
@ -247,9 +254,17 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
|
|||
this.add_prepared_report_buttons(data.doc);
|
||||
}
|
||||
this.toggle_message(false);
|
||||
|
||||
if (data.result && data.result.length) {
|
||||
this.render_chart(data);
|
||||
this.render_report(data);
|
||||
this.prepare_report_data(data);
|
||||
|
||||
const chart_options = this.get_chart_options(data);
|
||||
this.$chart.empty();
|
||||
if(chart_options) {
|
||||
this.render_chart(chart_options);
|
||||
}
|
||||
|
||||
this.render_datatable();
|
||||
} else {
|
||||
this.toggle_nothing_to_show(true);
|
||||
}
|
||||
|
|
@ -303,12 +318,15 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
|
|||
}
|
||||
}
|
||||
|
||||
render_report(data) {
|
||||
prepare_report_data(data) {
|
||||
this.raw_data = data;
|
||||
this.columns = this.prepare_columns(data.columns);
|
||||
this.data = this.prepare_data(data.result);
|
||||
|
||||
this.tree_report = this.data.some(d => 'indent' in d);
|
||||
}
|
||||
|
||||
render_datatable() {
|
||||
if (this.datatable) {
|
||||
this.datatable.refresh(this.data, this.columns);
|
||||
return;
|
||||
|
|
@ -323,21 +341,157 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
|
|||
});
|
||||
}
|
||||
|
||||
render_chart(data) {
|
||||
this.$chart.empty();
|
||||
let opts = this.report_settings.get_chart_data
|
||||
get_chart_options(data) {
|
||||
let options = this.report_settings.get_chart_data
|
||||
? this.report_settings.get_chart_data(data.columns, data.result)
|
||||
: data.chart
|
||||
? data.chart
|
||||
: {};
|
||||
if (!(opts.data && opts.data.labels && opts.data.labels.length > 0)) return;
|
||||
: undefined;
|
||||
|
||||
Object.assign(opts, {
|
||||
height: 200
|
||||
if (!(options && options.data && options.data.labels && options.data.labels.length > 0)) return;
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
render_chart(options, height=200) {
|
||||
Object.assign(options, {
|
||||
height: height
|
||||
});
|
||||
|
||||
this.$chart.empty();
|
||||
this.chart = new Chart(this.$chart[0], options);
|
||||
this.$chart.show();
|
||||
this.chart = new Chart(this.$chart[0], opts);
|
||||
}
|
||||
|
||||
get_possible_chart_options() {
|
||||
const columns = this.raw_data.columns;
|
||||
const rows = this.raw_data.result;
|
||||
const first_row = rows[0];
|
||||
const has_total_row = this.raw_data.add_total_row;
|
||||
|
||||
const indices = first_row.reduce((accumulator, current_value, current_index) => {
|
||||
if(!isNaN(Number(current_value))) {
|
||||
accumulator.push(current_index);
|
||||
}
|
||||
return accumulator;
|
||||
}, []);
|
||||
|
||||
function get_column_values(column_name) {
|
||||
const column_index = columns.indexOf(column_name);
|
||||
return rows.map(row => row[column_index]);
|
||||
}
|
||||
|
||||
function get_chart_options({ y_field, x_field, chart_type, color }) {
|
||||
const type = chart_type.toLowerCase();
|
||||
const colors = color ? [color] : undefined;
|
||||
|
||||
let labels = get_column_values(x_field)
|
||||
.filter(Boolean)
|
||||
.map(d => d.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
let dataset_values = get_column_values(y_field).map(d => Number(d));
|
||||
|
||||
if(has_total_row) {
|
||||
labels = labels.slice(0, -1);
|
||||
dataset_values = dataset_values.slice(0, -1);
|
||||
}
|
||||
|
||||
return {
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{ values: dataset_values }
|
||||
]
|
||||
},
|
||||
type: type,
|
||||
colors: colors
|
||||
};
|
||||
}
|
||||
|
||||
function preview_chart() {
|
||||
const wrapper = $(dialog.fields_dict["chart_preview"].wrapper);
|
||||
const values = dialog.get_values(true);
|
||||
let options = get_chart_options(values);
|
||||
|
||||
Object.assign(options, {
|
||||
height: 150
|
||||
});
|
||||
|
||||
wrapper.empty();
|
||||
new Chart(wrapper[0], options);
|
||||
wrapper.find('.chart-container .title, .chart-container .sub-title').hide();
|
||||
wrapper.show();
|
||||
}
|
||||
|
||||
const numeric_fields = columns.filter((col, i) => indices.includes(i));
|
||||
const non_numeric_fields = columns.filter((col, i) => !indices.includes(i))
|
||||
|
||||
const dialog = new frappe.ui.Dialog({
|
||||
title: __('Make Chart'),
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'y_field',
|
||||
label: 'Y Field',
|
||||
fieldtype: 'Select',
|
||||
options: numeric_fields,
|
||||
default: numeric_fields[0],
|
||||
onchange: preview_chart
|
||||
},
|
||||
{
|
||||
fieldname: 'x_field',
|
||||
label: 'X Field',
|
||||
fieldtype: 'Select',
|
||||
options: non_numeric_fields,
|
||||
default: non_numeric_fields[0],
|
||||
onchange: preview_chart
|
||||
},
|
||||
{
|
||||
fieldname: 'cb_1',
|
||||
fieldtype: 'Column Break'
|
||||
},
|
||||
{
|
||||
fieldname: 'chart_type',
|
||||
label: 'Type of Chart',
|
||||
fieldtype: 'Select',
|
||||
options: ['Bar', 'Line', 'Percentage', 'Pie'],
|
||||
default: 'Bar',
|
||||
onchange: preview_chart
|
||||
},
|
||||
{
|
||||
fieldname: 'color',
|
||||
label: 'Color',
|
||||
fieldtype: 'Color',
|
||||
depends_on: doc => ['Bar', 'Line'].includes(doc.chart_type),
|
||||
onchange: preview_chart,
|
||||
},
|
||||
{
|
||||
fieldname: 'sb_1',
|
||||
fieldtype: 'Section Break',
|
||||
label: 'Chart Preview'
|
||||
},
|
||||
{
|
||||
fieldname: 'chart_preview',
|
||||
label: 'Chart Preview',
|
||||
fieldtype: 'HTML',
|
||||
}
|
||||
],
|
||||
primary_action_label: __('Make'),
|
||||
primary_action: (values) => {
|
||||
let options = get_chart_options(values);
|
||||
|
||||
options.title = __(`${this.report_name}: ${values.y_field} vs ${values.x_field}`);
|
||||
|
||||
this.render_chart(options);
|
||||
|
||||
dialog.hide();
|
||||
}
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
|
||||
// load preview after dialog animation
|
||||
setTimeout(preview_chart, 500);
|
||||
}
|
||||
|
||||
get_user_settings() {
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
this.chart = new Chart(this.$charts_wrapper[0], {
|
||||
title: __("{0} Chart", [this.doctype]),
|
||||
data: data,
|
||||
type: args.chart_type, // 'bar', 'line', 'scatter', 'pie', 'percentage'
|
||||
type: args.chart_type,
|
||||
height: 150,
|
||||
colors: ['violet', 'light-blue', 'orange', 'red'],
|
||||
|
||||
|
|
@ -365,7 +365,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
{
|
||||
label: __('Chart Type'),
|
||||
fieldtype: 'Select',
|
||||
options: ['Bar', 'Line', 'Scatter', 'Pie', 'Percentage'],
|
||||
options: ['Bar', 'Line', 'Pie', 'Percentage'],
|
||||
fieldname: 'chart_type',
|
||||
default: toTitle(defaults.chart_type || 'Bar')
|
||||
}
|
||||
|
|
@ -396,6 +396,9 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
|
|||
// look like strings and also
|
||||
// monkey patch the doc
|
||||
// javascript is awesome
|
||||
|
||||
// O.o
|
||||
|
||||
return {
|
||||
doc: d,
|
||||
toString() {
|
||||
|
|
|
|||
|
|
@ -386,6 +386,10 @@ h6.uppercase, .h6.uppercase {
|
|||
}
|
||||
}
|
||||
|
||||
.timeline-item .media-body {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.timeline-item.user-content {
|
||||
margin: 30px 0px 30px 27px;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ queue_timeout = {
|
|||
|
||||
redis_connection = None
|
||||
|
||||
def enqueue(method, queue='default', timeout=300, event=None,
|
||||
def enqueue(method, queue='default', timeout=None, event=None,
|
||||
is_async=True, job_name=None, now=False, enqueue_after_commit=False, **kwargs):
|
||||
'''
|
||||
Enqueue method to be executed using a background worker
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import requests
|
|||
import subprocess # nosec
|
||||
from frappe.utils import cstr
|
||||
from frappe.utils.gitutils import get_app_last_commit_ref, get_app_branch
|
||||
from frappe import _
|
||||
import subprocess # nosec
|
||||
from frappe import _, safe_decode
|
||||
|
||||
def get_change_log(user=None):
|
||||
if not user: user = frappe.session.user
|
||||
|
|
@ -118,15 +118,21 @@ def get_versions():
|
|||
def get_app_branch(app):
|
||||
'''Returns branch of an app'''
|
||||
try:
|
||||
return subprocess.check_output('cd ../apps/{0} && git rev-parse --abbrev-ref HEAD'.format(app),
|
||||
shell=True).strip()
|
||||
result = subprocess.check_output('cd ../apps/{0} && git rev-parse --abbrev-ref HEAD'.format(app),
|
||||
shell=True)
|
||||
result = safe_decode(result)
|
||||
result = result.strip()
|
||||
return result
|
||||
except Exception as e:
|
||||
return ''
|
||||
|
||||
def get_app_last_commit_ref(app):
|
||||
try:
|
||||
return subprocess.check_output('cd ../apps/{0} && git rev-parse HEAD'.format(app),
|
||||
shell=True).strip()[:7]
|
||||
result = subprocess.check_output('cd ../apps/{0} && git rev-parse HEAD --short 7'.format(app),
|
||||
shell=True)
|
||||
result = safe_decode(result)
|
||||
result = result.strip()
|
||||
return result
|
||||
except Exception as e:
|
||||
return ''
|
||||
|
||||
|
|
@ -159,7 +165,7 @@ def check_release_on_github(app):
|
|||
# Check if repo remote is on github
|
||||
from subprocess import CalledProcessError
|
||||
try:
|
||||
remote_url = subprocess.check_output("cd ../apps/{} && git ls-remote --get-url".format(app), shell=True)
|
||||
remote_url = subprocess.check_output("cd ../apps/{} && git ls-remote --get-url".format(app), shell=True).decode()
|
||||
except CalledProcessError:
|
||||
# Passing this since some apps may not have git initializaed in them
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -24,17 +24,18 @@ def get_permission_query_conditions(user):
|
|||
|
||||
return "(`tabWorkflow Action`.`user`='{user}')".format(user=user)
|
||||
|
||||
|
||||
def has_permission(doc, user):
|
||||
if user not in ['Administrator', doc.user]:
|
||||
return False
|
||||
|
||||
|
||||
def process_workflow_actions(doc, state):
|
||||
|
||||
workflow = get_workflow_name(doc.get('doctype'))
|
||||
if not workflow: return
|
||||
|
||||
if state == "on_trash":
|
||||
clear_workflow_actions(doc.get('doctype'), doc.get('name'))
|
||||
return
|
||||
|
||||
if is_workflow_action_already_created(doc): return
|
||||
|
||||
clear_old_workflow_actions(doc)
|
||||
|
|
@ -54,7 +55,6 @@ def process_workflow_actions(doc, state):
|
|||
if send_email_alert(workflow):
|
||||
enqueue(send_workflow_action_email, queue='short', users_data=list(user_data_map.values()), doc=doc)
|
||||
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def apply_action(action, doctype, docname, current_state, user=None, last_modified=None):
|
||||
if not verify_request():
|
||||
|
|
@ -234,6 +234,14 @@ def is_workflow_action_already_created(doc):
|
|||
'workflow_state': get_doc_workflow_state(doc)
|
||||
})
|
||||
|
||||
def clear_workflow_actions(doctype, name):
|
||||
if not (doctype and name):
|
||||
return
|
||||
|
||||
frappe.db.sql('''delete from `tabWorkflow Action`
|
||||
where reference_doctype=%s and reference_name=%s''',
|
||||
(doctype, name))
|
||||
|
||||
def get_doc_workflow_state(doc):
|
||||
workflow_name = get_workflow_name(doc.get('doctype'))
|
||||
workflow_state_field = get_workflow_state_field(workflow_name)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue