diff --git a/frappe/__init__.py b/frappe/__init__.py index b312809617..673c0521b8 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -1422,7 +1422,7 @@ def enqueue(*args, **kwargs): :param queue: (optional) should be either long, default or short :param timeout: (optional) should be set according to the functions :param event: this is passed to enable clearing of jobs from queues - :param async: (optional) if async=False, the method is executed immediately, else via a worker + :param is_async: (optional) if is_async=False, the method is executed immediately, else via a worker :param job_name: (optional) can be used to name an enqueue call, which can be used to prevent duplicate calls :param kwargs: keyword arguments to be passed to the method ''' @@ -1589,4 +1589,4 @@ def mock(type, size = 1, locale = 'en'): results = squashify(results) - return results \ No newline at end of file + return results diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 6005389481..4135468c41 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -1019,7 +1019,7 @@ def reset_otp_secret(user): 'delayed':False, 'retry':3 } - enqueue(method=frappe.sendmail, queue='short', timeout=300, event=None, async=True, job_name=None, now=False, **email_args) + enqueue(method=frappe.sendmail, queue='short', timeout=300, event=None, is_async=True, job_name=None, now=False, **email_args) return frappe.msgprint(_("OTP Secret has been reset. Re-registration will be required on next login.")) else: return frappe.throw(_("OTP secret can only be reset by the Administrator.")) diff --git a/frappe/database.py b/frappe/database.py index 94092e4ea1..14a61b22b7 100644 --- a/frappe/database.py +++ b/frappe/database.py @@ -975,7 +975,7 @@ class Database: def enqueue_jobs_after_commit(): if frappe.flags.enqueue_after_commit and len(frappe.flags.enqueue_after_commit) > 0: for job in frappe.flags.enqueue_after_commit: - q = get_queue(job.get("queue"), async=job.get("async")) + q = get_queue(job.get("queue"), is_async=job.get("is_async")) q.enqueue_call(execute_job, timeout=job.get("timeout"), kwargs=job.get("queue_args")) frappe.flags.enqueue_after_commit = [] diff --git a/frappe/handler.py b/frappe/handler.py index 8543beeac6..db95ad4a96 100755 --- a/frappe/handler.py +++ b/frappe/handler.py @@ -21,7 +21,8 @@ def handle(): if cmd!='login': data = execute_cmd(cmd) - if data: + # data can be an empty string or list which are valid responses + if data is not None: if isinstance(data, Response): # method returns a response object, pass it on return data diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 9ab27fbd4a..6348f66b55 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -80,7 +80,7 @@ def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reloa doc.run_method('on_change') frappe.enqueue('frappe.model.delete_doc.delete_dynamic_links', doctype=doc.doctype, name=doc.name, - async=False if frappe.flags.in_test else True) + is_async=False if frappe.flags.in_test else True) # check if links exist if not force: @@ -324,4 +324,3 @@ def insert_feed(doc): "subject": "{0} {1}".format(_(doc.doctype), doc.name), "full_name": get_fullname(doc.owner) }).insert(ignore_permissions=True) - diff --git a/frappe/public/css/desk-rtl.css b/frappe/public/css/desk-rtl.css index 45b320cd9d..3d763ab521 100644 --- a/frappe/public/css/desk-rtl.css +++ b/frappe/public/css/desk-rtl.css @@ -22,7 +22,6 @@ body.no-breadcrumbs .navbar .navbar-home:before { .layout-side-section .overlay-sidebar { left: auto !important; right: 0 !important; - transform:translateX(110%) !important; } .layout-side-section .overlay-sidebar.opened { transform:translateX(0) !important; diff --git a/frappe/public/js/frappe/form/dashboard.js b/frappe/public/js/frappe/form/dashboard.js index 15700f7cd7..3786a45f1c 100644 --- a/frappe/public/js/frappe/form/dashboard.js +++ b/frappe/public/js/frappe/form/dashboard.js @@ -359,9 +359,7 @@ frappe.ui.form.Dashboard = Class.extend({ update_heatmap: function(data) { if(this.heatmap) { - this.heatmap.update({ - dataPoints: data - }); + this.heatmap.update(data); } }, diff --git a/frappe/public/js/frappe/ui/dialog.js b/frappe/public/js/frappe/ui/dialog.js index b51bb0eca3..2cb9185bc8 100644 --- a/frappe/public/js/frappe/ui/dialog.js +++ b/frappe/public/js/frappe/ui/dialog.js @@ -6,16 +6,18 @@ frappe.provide('frappe.ui'); window.cur_dialog = null; frappe.ui.open_dialogs = []; -frappe.ui.Dialog = frappe.ui.FieldGroup.extend({ - init: function(opts) { + +frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup { + constructor(opts) { this.display = false; this.is_dialog = true; $.extend(this, { animate: true, size: null }, opts); - this._super(); + super(); this.make(); - }, - make: function() { + } + + make() { this.$wrapper = frappe.get_modal("", ""); this.wrapper = this.$wrapper.find('.modal-dialog') @@ -33,7 +35,7 @@ frappe.ui.Dialog = frappe.ui.FieldGroup.extend({ this.header = this.$wrapper.find(".modal-header"); // make fields (if any) - this._super(); + super.make(); // show footer this.action = this.action || { primary: { }, secondary: { } }; @@ -42,6 +44,10 @@ frappe.ui.Dialog = frappe.ui.FieldGroup.extend({ this.primary_action || this.action.primary.onsubmit); } + if(this.secondary_action) { + this.set_secondary_action(this.secondary_action); + } + if (this.secondary_action_label || (this.action.secondary && this.action.secondary.label)) { this.get_close_btn().html(this.secondary_action_label || this.action.secondary.label); } @@ -50,6 +56,8 @@ frappe.ui.Dialog = frappe.ui.FieldGroup.extend({ this.$wrapper .on("hide.bs.modal", function() { me.display = false; + me.secondary_action && me.secondary_action(); + if(frappe.ui.open_dialogs[frappe.ui.open_dialogs.length-1]===me) { frappe.ui.open_dialogs.pop(); if(frappe.ui.open_dialogs.length) { @@ -77,23 +85,24 @@ frappe.ui.Dialog = frappe.ui.FieldGroup.extend({ } }); - }, - get_primary_btn: function() { - return this.$wrapper.find(".modal-header .btn-primary"); - }, + } - set_message: function(text) { + get_primary_btn() { + return this.$wrapper.find(".modal-header .btn-primary"); + } + + set_message(text) { this.$message.removeClass('hide'); this.$body.addClass('hide'); this.$message.text(text); - }, + } clear_message() { this.$message.addClass('hide'); this.$body.removeClass('hide'); - }, + } - set_primary_action: function(label, click) { + set_primary_action(label, click) { this.has_primary_action = true; var me = this; return this.get_primary_btn() @@ -108,20 +117,25 @@ frappe.ui.Dialog = frappe.ui.FieldGroup.extend({ if(!values) return; click && click.apply(me, [values]); }); - }, - disable_primary_action: function() { + } + + set_secondary_action(click) { + this.get_close_btn().on('click', click); + } + + disable_primary_action() { this.get_primary_btn().addClass('disabled'); - }, - enable_primary_action: function() { + } + enable_primary_action() { this.get_primary_btn().removeClass('disabled'); - }, - make_head: function() { + } + make_head() { this.set_title(this.title); - }, - set_title: function(t) { + } + set_title(t) { this.$wrapper.find(".modal-title").html(t); - }, - show: function() { + } + show() { // show it if ( this.animate ) { this.$wrapper.addClass('fade'); @@ -131,19 +145,20 @@ frappe.ui.Dialog = frappe.ui.FieldGroup.extend({ this.$wrapper.modal("show"); this.primary_action_fulfilled = false; this.is_visible = true; - }, - hide: function() { + } + hide() { this.$wrapper.modal("hide"); this.is_visible = false; - }, - get_close_btn: function() { + } + get_close_btn() { return this.$wrapper.find(".btn-modal-close"); - }, - no_cancel: function() { + } + no_cancel() { this.get_close_btn().toggle(false); - }, - cancel: function() { + } + cancel() { this.get_close_btn().trigger("click"); } -}); +}; + diff --git a/frappe/public/less/flex.less b/frappe/public/less/flex.less index 72e28977d6..f68946487a 100644 --- a/frappe/public/less/flex.less +++ b/frappe/public/less/flex.less @@ -14,6 +14,14 @@ align-items: center; } +.align-flex-end { + align-items: flex-end; +} + +.justify-between { + justify-content: space-between +} + .level { display: flex; justify-content: space-between; @@ -48,4 +56,4 @@ flex-grow: 0; flex-shrink: 0; justify-content: center; -} \ No newline at end of file +} diff --git a/frappe/tests/data/email_with_image.txt b/frappe/tests/data/email_with_image.txt index cd97873312..57451c41a7 100644 --- a/frappe/tests/data/email_with_image.txt +++ b/frappe/tests/data/email_with_image.txt @@ -1,22 +1,22 @@ -Delivered-To: support@xxx.com +Delivered-To: support@example.com Received: by 10.140.27.240 with SMTP id 103csp1321115qgx; Mon, 7 Mar 2016 05:45:25 -0800 (PST) X-Received: by 10.98.13.132 with SMTP id 4mr897053pfn.122.1457358325425; Mon, 07 Mar 2016 05:45:25 -0800 (PST) -Return-Path: +Return-Path: Received: from mail-pa0-x231.google.com (mail-pa0-x231.google.com. [2607:f8b0:400e:c03::231]) by mx.google.com with ESMTPS id xc7si8177568pab.217.2016.03.07.05.45.24 - for + for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Mar 2016 05:45:24 -0800 (PST) -Received-SPF: pass (google.com: domain of sukh@yyy.com designates 2607:f8b0:400e:c03::231 as permitted sender) client-ip=2607:f8b0:400e:c03::231; +Received-SPF: pass (google.com: domain of sukh@example.com designates 2607:f8b0:400e:c03::231 as permitted sender) client-ip=2607:f8b0:400e:c03::231; Authentication-Results: mx.google.com; - spf=pass (google.com: domain of sukh@yyy.com designates 2607:f8b0:400e:c03::231 as permitted sender) smtp.mailfrom=sukh@yyy.com; - dkim=temperror (no key for signature) header.i=@yyy.com + spf=pass (google.com: domain of sukh@example.com designates 2607:f8b0:400e:c03::231 as permitted sender) smtp.mailfrom=sukh@example.com; + dkim=temperror (no key for signature) header.i=@example.com Received: by mail-pa0-x231.google.com with SMTP id fy10so78799490pac.1 - for ; Mon, 07 Mar 2016 05:45:24 -0800 (PST) + for ; Mon, 07 Mar 2016 05:45:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=yyy.com; s=march; + d=example.com; s=march; h=from:message-id:mime-version:subject:date:references:to:in-reply-to; bh=yeuhcbT1UUBa85dfYr4MvEHUnO1nUwaDjTSXp+RTZqc=; b=i7tr2P4icc73830T3HGAWbtn3O4J0hbOexxNEIvjSnm65Xbb6NrH/JK5KNd2FRN0uh @@ -36,21 +36,21 @@ X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; X-Gm-Message-State: AD7BkJJkB6+rEJ77M+sJg7jWjs9f9i2vHLJsAx76mKbkNJbiz0HooCVaM9yb8sVm7j1Xug== X-Received: by 10.66.250.199 with SMTP id ze7mr33646221pac.103.1457358324406; Mon, 07 Mar 2016 05:45:24 -0800 (PST) -Return-Path: +Return-Path: Received: from [10.0.1.3] ([49.248.43.226]) by smtp.gmail.com with ESMTPSA id x64sm24358984pfa.72.2016.03.07.05.45.15 - for + for (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 07 Mar 2016 05:45:23 -0800 (PST) -From: Sukh Dugal +From: Sukh Dugal Content-Type: multipart/alternative; boundary="Apple-Mail=_932090B1-CF85-48AE-A8FA-95F2EEB1A521" -Message-Id: <444FBF29-EE23-4698-A38F-DD1081ABB362@yyy.com> +Message-Id: <444FBF29-EE23-4698-A38F-DD1081ABB362@example.com> Mime-Version: 1.0 (Mac OS X Mail 9.2 \(3112\)) Subject: Re: 1 minute review 🦄🌈😎 Date: Mon, 7 Mar 2016 19:15:12 +0530 -References: <7c38972ae7@frappe.xxx.com> -To: support@xxx.com -In-Reply-To: <7c38972ae7@frappe.xxx.com> +References: <7c38972ae7@frappe.example.com> +To: support@example.com +In-Reply-To: <7c38972ae7@frappe.example.com> X-Mailer: Apple Mail (2.3112) @@ -64,7 +64,7 @@ It should ideally be open like #1 but I=E2=80=99d love 2. -On 07-Mar-2016, at 5:47 PM, Rushabh Mehta wrote: +On 07-Mar-2016, at 5:47 PM, Rushabh Mehta wrote: >=20 > Thanks for the feedback! >=20 @@ -88,13 +88,13 @@ On 07-Mar-2016, at 5:47 PM, Rushabh Mehta wrote: removing any features >=20 > Agree! -> This email was sent to sukh@yyy.com +> This email was sent to sukh@example.com > Leave this conversation = - > Frappe Technologies Private Limited -> Sent via ERPNext +> Sent via ERPNext --Apple-Mail=_932090B1-CF85-48AE-A8FA-95F2EEB1A521 @@ -122,7 +122,7 @@ id=3D"0740E45B-C8EE-4972-8524-13BB62334D85" height=3D"527" width=3D"697" = apple-width=3D"yes" apple-height=3D"yes" = src=3D"cid:DC6C108B-9D1B-489E-AEB8-341FADFB4F39" class=3D"">
On 07-Mar-2016, at 5:47 PM, Rushabh Mehta <rushabh@xxx.com>= +href=3D"mailto:rushabh@example.com" class=3D"">rushabh@example.com>= wrote:
@@ -164,11 +164,11 @@ data-email-footer=3D"true" class=3D"">
This email was sent to sukh@yyy.com +href=3D"mailto:sukh@example.com" class=3D"">sukh@example.com

Leave this conversation center; color: #8d99a6" class=3D"">Frappe Technologies Private = Limited

- Sent via ERPNext diff --git a/frappe/twofactor.py b/frappe/twofactor.py index 931f8c3d6c..35d7a28fcb 100644 --- a/frappe/twofactor.py +++ b/frappe/twofactor.py @@ -288,7 +288,7 @@ def send_token_via_sms(otpsecret, token=None, phone_no=None): 'use_post': ss.use_post } enqueue(method=send_request, queue='short', timeout=300, event=None, - async=True, job_name=None, now=False, **sms_args) + is_async=True, job_name=None, now=False, **sms_args) return True def send_token_via_email(user, token, otp_secret, otp_issuer, subject=None, message=None): @@ -315,7 +315,7 @@ def send_token_via_email(user, token, otp_secret, otp_issuer, subject=None, mess } enqueue(method=frappe.sendmail, queue='short', timeout=300, event=None, - async=True, job_name=None, now=False, **email_args) + is_async=True, job_name=None, now=False, **email_args) return True def get_qr_svg_code(totp_uri): diff --git a/frappe/utils/background_jobs.py b/frappe/utils/background_jobs.py index 5c08dc7969..9f75b1b744 100755 --- a/frappe/utils/background_jobs.py +++ b/frappe/utils/background_jobs.py @@ -24,7 +24,7 @@ queue_timeout = { redis_connection = None def enqueue(method, queue='default', timeout=300, event=None, - async=True, job_name=None, now=False, enqueue_after_commit=False, **kwargs): + is_async=True, job_name=None, now=False, enqueue_after_commit=False, **kwargs): ''' Enqueue method to be executed using a background worker @@ -32,15 +32,20 @@ def enqueue(method, queue='default', timeout=300, event=None, :param queue: should be either long, default or short :param timeout: should be set according to the functions :param event: this is passed to enable clearing of jobs from queues - :param async: if async=False, the method is executed immediately, else via a worker + :param is_async: if is_async=False, the method is executed immediately, else via a worker :param job_name: can be used to name an enqueue call, which can be used to prevent duplicate calls :param now: if now=True, the method is executed via frappe.call :param kwargs: keyword arguments to be passed to the method ''' + # To handle older implementations + if 'async' in kwargs: + is_async = True + del kwargs['async'] + if now or frappe.flags.in_migrate: return frappe.call(method, **kwargs) - q = get_queue(queue, async=async) + q = get_queue(queue, is_async=is_async) if not timeout: timeout = queue_timeout.get(queue) or 300 queue_args = { @@ -49,7 +54,7 @@ def enqueue(method, queue='default', timeout=300, event=None, "method": method, "event": event, "job_name": job_name or cstr(method), - "async": async, + "is_async": is_async, "kwargs": kwargs } if enqueue_after_commit: @@ -58,7 +63,7 @@ def enqueue(method, queue='default', timeout=300, event=None, frappe.flags.enqueue_after_commit.append({ "queue": queue, - "async": async, + "is_async": is_async, "timeout": timeout, "queue_args":queue_args }) @@ -76,11 +81,11 @@ def enqueue_doc(doctype, name=None, method=None, queue='default', timeout=300, def run_doc_method(doctype, name, doc_method, **kwargs): getattr(frappe.get_doc(doctype, name), doc_method)(**kwargs) -def execute_job(site, method, event, job_name, kwargs, user=None, async=True, retry=0): +def execute_job(site, method, event, job_name, kwargs, user=None, is_async=True, retry=0): '''Executes job in a worker, performs commit/rollback and logs if there is any error''' from frappe.utils.scheduler import log - if async: + if is_async: frappe.connect(site) if os.environ.get('CI'): frappe.flags.in_test = True @@ -110,7 +115,7 @@ def execute_job(site, method, event, job_name, kwargs, user=None, async=True, re time.sleep(retry+1) return execute_job(site, method, event, job_name, kwargs, - async=async, retry=retry+1) + is_async=is_async, retry=retry+1) else: log(method_name, message=repr(locals())) @@ -125,7 +130,7 @@ def execute_job(site, method, event, job_name, kwargs, user=None, async=True, re frappe.db.commit() finally: - if async: + if is_async: frappe.destroy() def start_worker(queue=None, quiet = False): @@ -193,11 +198,11 @@ def get_queue_list(queue_list=None): else: return default_queue_list -def get_queue(queue, async=True): +def get_queue(queue, is_async=True): '''Returns a Queue object tied to a redis connection''' validate_queue(queue) - return Queue(queue, connection=get_redis_conn(), async=async) + return Queue(queue, connection=get_redis_conn(), async=is_async) def validate_queue(queue, default_queue_list=None): if not default_queue_list: @@ -226,4 +231,4 @@ def enqueue_test_job(): def test_job(s): import time print('sleeping...') - time.sleep(s) \ No newline at end of file + time.sleep(s) diff --git a/frappe/utils/xlsxutils.py b/frappe/utils/xlsxutils.py index c50a149adb..880726c16e 100644 --- a/frappe/utils/xlsxutils.py +++ b/frappe/utils/xlsxutils.py @@ -46,6 +46,8 @@ def make_xlsx(data, sheet_name, wb=None): def handle_html(data): # return if no html tags found + data = frappe.as_unicode(data) + if '<' not in data: return data if '>' not in data: diff --git a/frappe/website/js/web_form.js b/frappe/website/js/web_form.js index 79f8ce9e51..bbb2aadc0c 100644 --- a/frappe/website/js/web_form.js +++ b/frappe/website/js/web_form.js @@ -53,7 +53,6 @@ frappe.ready(function() { // submit $(".btn-form-submit").on("click", function() { - let data = frappe.web_form.get_values(); save(); return false; });