- | {{ j.queue.split(".").slice(-1)[0] }} |
+ {{ j.queue.split(".").slice(-1)[0] }} |
{{ frappe.utils.encode_tags(j.job_name) }}
diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js
index 4ade51ae5b..9f1bf0eca8 100644
--- a/frappe/custom/doctype/customize_form/customize_form.js
+++ b/frappe/custom/doctype/customize_form/customize_form.js
@@ -17,6 +17,14 @@ frappe.ui.form.on("Customize Form", {
};
});
+ frm.set_query("default_print_format", function() {
+ return {
+ filters: {
+ 'print_format_type': ['!=', 'JS']
+ }
+ }
+ });
+
$(frm.wrapper).on("grid-row-render", function(e, grid_row) {
if(grid_row.doc && grid_row.doc.fieldtype=="Section Break") {
$(grid_row.row).css({"font-weight": "bold"});
diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.js b/frappe/desk/doctype/dashboard_chart/dashboard_chart.js
index a330f7e97e..d51231097e 100644
--- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.js
+++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.js
@@ -114,9 +114,8 @@ frappe.ui.form.on('Dashboard Chart', {
} else {
// standard filters
if (frm.doc.document_type) {
- // allow all link and select fields as filters
- frm.chart_filters = [];
frappe.model.with_doctype(frm.doc.document_type, () => {
+ frm.chart_filters = [];
frappe.get_meta(frm.doc.document_type).fields.map(df => {
if (['Link', 'Select'].includes(df.fieldtype)) {
let _df = copy_dict(df);
@@ -131,8 +130,8 @@ frappe.ui.form.on('Dashboard Chart', {
frm.chart_filters.push(_df);
}
- frm.trigger('render_filters_table');
});
+ frm.trigger('render_filters_table');
});
}
}
@@ -158,7 +157,7 @@ frappe.ui.form.on('Dashboard Chart', {
let filters = JSON.parse(frm.doc.filters_json || '{}');
var filters_set = false;
- fields.map( f => {
+ fields.map(f => {
if (filters[f.fieldname]) {
const filter_row = $(` |
| ${f.label} | ${filters[f.fieldname] || ""} |
`);
table.find('tbody').append(filter_row);
diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py
index dca1a99802..f5d2d58e04 100644
--- a/frappe/desk/query_report.py
+++ b/frappe/desk/query_report.py
@@ -229,7 +229,7 @@ def get_prepared_report_result(report, filters, dn="", user=None):
"status": "Completed",
"filters": json.dumps(filters),
"owner": user,
- "report_name": report.custom_report or report.report_name
+ "report_name": report.get('custom_report') or report.get('report_name')
},
order_by = 'creation desc'
)
diff --git a/frappe/integrations/doctype/stripe_settings/stripe_settings.py b/frappe/integrations/doctype/stripe_settings/stripe_settings.py
index 35beef7faa..70ca6002e4 100644
--- a/frappe/integrations/doctype/stripe_settings/stripe_settings.py
+++ b/frappe/integrations/doctype/stripe_settings/stripe_settings.py
@@ -76,7 +76,7 @@ class StripeSettings(Document):
def create_charge_on_stripe(self):
import stripe
try:
- charge = stripe.Charge.create(amount=cint(flt(self.data.amount)*100), currency=self.data.currency, source=self.data.stripe_token_id, description=self.data.description)
+ charge = stripe.Charge.create(amount=cint(flt(self.data.amount)*100), currency=self.data.currency, source=self.data.stripe_token_id, description=self.data.description, receipt_email=self.data.payer_email)
if charge.captured == True:
self.integration_request.db_set('status', 'Completed', update_modified=False)
diff --git a/frappe/integrations/doctype/webhook/webhook.js b/frappe/integrations/doctype/webhook/webhook.js
index 90b5b12dc6..09c296113a 100644
--- a/frappe/integrations/doctype/webhook/webhook.js
+++ b/frappe/integrations/doctype/webhook/webhook.js
@@ -66,6 +66,10 @@ frappe.ui.form.on('Webhook', {
webhook_doctype: (frm) => {
frappe.webhook.set_fieldname_select(frm);
+ },
+
+ enable_security: (frm) => {
+ frm.toggle_reqd('webhook_secret', frm.doc.enable_security);
}
});
diff --git a/frappe/integrations/doctype/webhook/webhook.json b/frappe/integrations/doctype/webhook/webhook.json
index 8aa96e6859..9f979099c9 100644
--- a/frappe/integrations/doctype/webhook/webhook.json
+++ b/frappe/integrations/doctype/webhook/webhook.json
@@ -19,6 +19,9 @@
"request_url",
"cb_webhook",
"request_structure",
+ "sb_security",
+ "enable_security",
+ "webhook_secret",
"sb_webhook_headers",
"webhook_headers",
"sb_webhook_data",
@@ -127,10 +130,27 @@
"fieldtype": "Select",
"label": "Naming Series",
"options": "\nHOOK-.####"
+ },
+ {
+ "fieldname": "sb_security",
+ "fieldtype": "Section Break",
+ "label": "Webhook Security"
+ },
+ {
+ "default": "0",
+ "fieldname": "enable_security",
+ "fieldtype": "Check",
+ "label": "Enable Security"
+ },
+ {
+ "depends_on": "eval:doc.enable_security == 1",
+ "fieldname": "webhook_secret",
+ "fieldtype": "Password",
+ "label": "Webhook Secret"
}
],
"links": [],
- "modified": "2020-01-06 02:51:07.997566",
+ "modified": "2020-01-13 01:53:04.459968",
"modified_by": "Administrator",
"module": "Integrations",
"name": "Webhook",
diff --git a/frappe/integrations/doctype/webhook/webhook.py b/frappe/integrations/doctype/webhook/webhook.py
index 0a97022f66..5cbe7c0a02 100644
--- a/frappe/integrations/doctype/webhook/webhook.py
+++ b/frappe/integrations/doctype/webhook/webhook.py
@@ -4,7 +4,10 @@
from __future__ import unicode_literals
+import base64
import datetime
+import hashlib
+import hmac
import json
from time import sleep
@@ -16,6 +19,8 @@ from frappe import _
from frappe.model.document import Document
from frappe.utils.jinja import validate_template
+WEBHOOK_SECRET_HEADER = "X-Frappe-Webhook-Signature"
+
class Webhook(Document):
def validate(self):
@@ -94,10 +99,23 @@ def enqueue_webhook(doc, webhook):
def get_webhook_headers(doc, webhook):
headers = {}
+
+ if webhook.enable_security:
+ data = get_webhook_data(doc, webhook)
+ signature = base64.b64encode(
+ hmac.new(
+ webhook.get_password("webhook_secret").encode("utf8"),
+ json.dumps(data).encode("utf8"),
+ hashlib.sha256
+ ).digest()
+ )
+ headers[WEBHOOK_SECRET_HEADER] = signature
+
if webhook.webhook_headers:
for h in webhook.webhook_headers:
if h.get("key") and h.get("value"):
headers[h.get("key")] = h.get("value")
+
return headers
diff --git a/frappe/integrations/oauth2_logins.py b/frappe/integrations/oauth2_logins.py
index a3ee98ad4e..14a6bcc417 100644
--- a/frappe/integrations/oauth2_logins.py
+++ b/frappe/integrations/oauth2_logins.py
@@ -31,6 +31,10 @@ def login_via_office365(code, state):
def login_via_salesforce(code, state):
login_via_oauth2("salesforce", code, state, decoder=decoder_compat)
+@frappe.whitelist(allow_guest=True)
+def login_via_fairlogin(code, state):
+ login_via_oauth2("fairlogin", code, state, decoder=decoder_compat)
+
@frappe.whitelist(allow_guest=True)
def custom(code, state):
"""
diff --git a/frappe/patches/v11_0/delete_all_prepared_reports.py b/frappe/patches/v11_0/delete_all_prepared_reports.py
index de36db66af..1d722da7e6 100644
--- a/frappe/patches/v11_0/delete_all_prepared_reports.py
+++ b/frappe/patches/v11_0/delete_all_prepared_reports.py
@@ -3,7 +3,7 @@ import frappe
def execute():
if frappe.db.table_exists('Prepared Report'):
- frappe.reload_doc("core", "doctype", "prepared_doctype")
+ frappe.reload_doc("core", "doctype", "prepared_report")
prepared_reports = frappe.get_all("Prepared Report")
for report in prepared_reports:
frappe.delete_doc("Prepared Report", report.name)
diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js
index 23d7bffec2..5e642f907b 100644
--- a/frappe/public/js/frappe/desk.js
+++ b/frappe/public/js/frappe/desk.js
@@ -481,7 +481,7 @@ frappe.Application = Class.extend({
// Iterate over changelog
var change_log_dialog = frappe.msgprint({
message: frappe.render_template("change_log", {"change_log": change_log}),
- title: __("Updated To New Version 🎉"),
+ title: __("Updated To A New Version 🎉"),
wide: true,
scroll: true
});
diff --git a/frappe/public/js/frappe/form/controls/geolocation.js b/frappe/public/js/frappe/form/controls/geolocation.js
index d68f6254b9..9dfad09299 100644
--- a/frappe/public/js/frappe/form/controls/geolocation.js
+++ b/frappe/public/js/frappe/form/controls/geolocation.js
@@ -1,4 +1,6 @@
-frappe.ui.form.ControlGeolocation = frappe.ui.form.ControlCode.extend({
+frappe.ui.form.ControlGeolocation = frappe.ui.form.ControlData.extend({
+ horizontal: false,
+
make_wrapper() {
// Create the elements for map area
this._super();
diff --git a/frappe/public/js/frappe/form/footer/timeline.js b/frappe/public/js/frappe/form/footer/timeline.js
index 6dbb7904c2..8294c3f7b8 100644
--- a/frappe/public/js/frappe/form/footer/timeline.js
+++ b/frappe/public/js/frappe/form/footer/timeline.js
@@ -371,6 +371,10 @@ frappe.ui.form.Timeline = class Timeline {
c.sender = c.sender.split("<")[1].split(">")[0];
}
+ if (!c.doctype && ['Comment', 'Communication'].includes(c.communication_type)) {
+ c.doctype = c.communication_type;
+ }
+
c.user_info = frappe.user_info(c.sender);
c["delete"] = "";
diff --git a/frappe/public/js/frappe/form/grid.js b/frappe/public/js/frappe/form/grid.js
index 6c66362426..3960833028 100644
--- a/frappe/public/js/frappe/form/grid.js
+++ b/frappe/public/js/frappe/form/grid.js
@@ -65,26 +65,22 @@ export default class Grid {