Merge branch 'develop' into staging

This commit is contained in:
Nabin Hait 2018-08-21 12:47:58 +05:30
commit f28eb5ac1e
14 changed files with 111 additions and 85 deletions

View file

@ -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
return results

View file

@ -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."))

View file

@ -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 = []

View file

@ -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

View file

@ -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)

View file

@ -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;

View file

@ -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);
}
},

View file

@ -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");
}
});
};

View file

@ -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;
}
}

View file

@ -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: <sukh@yyy.com>
Return-Path: <sukh@example.com>
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 <support@xxx.com>
for <support@example.com>
(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 <support@xxx.com>; Mon, 07 Mar 2016 05:45:24 -0800 (PST)
for <support@example.com>; 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: <sukh@yyy.com>
Return-Path: <sukh@example.com>
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 <support@xxx.com>
for <support@example.com>
(version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128);
Mon, 07 Mar 2016 05:45:23 -0800 (PST)
From: Sukh Dugal <sukh@yyy.com>
From: Sukh Dugal <sukh@example.com>
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 <rushabh@xxx.com> wrote:
On 07-Mar-2016, at 5:47 PM, Rushabh Mehta <rushabh@example.com> wrote:
>=20
> Thanks for the feedback!
>=20
@ -88,13 +88,13 @@ On 07-Mar-2016, at 5:47 PM, Rushabh Mehta <rushabh@xxx.com> 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 =
<http://frappe.xxx.com/api/method/frappe.email.bulk.unsubscribe?email=3D=
sukh%40yyy.com&name=3DWN-SUP17470&doctype=3DIssue&_signature=3Dbba=
<http://frappe.example.com/api/method/frappe.email.bulk.unsubscribe?email=3D=
sukh%40example.com&name=3DWN-SUP17470&doctype=3DIssue&_signature=3Dbba=
bf063b4f3aad9ba1af915aa66df23>
> Frappe Technologies Private Limited
> Sent via ERPNext <https://xxx.com/?source=3Dvia_email_footer>
> Sent via ERPNext <https://example.com/?source=3Dvia_email_footer>
--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""></div><div =
class=3D"">On 07-Mar-2016, at 5:47 PM, Rushabh Mehta &lt;<a =
href=3D"mailto:rushabh@xxx.com" class=3D"">rushabh@xxx.com</a>&gt;=
href=3D"mailto:rushabh@example.com" class=3D"">rushabh@example.com</a>&gt;=
wrote:</div><div class=3D""><div><blockquote type=3D"cite" class=3D""><br=
class=3D"Apple-interchange-newline"><div class=3D"">
@ -164,11 +164,11 @@ data-email-footer=3D"true" class=3D"">
<div style=3D"margin: 15px auto; padding: 0px 7px; text-align: =
center; color: #8d99a6;" class=3D"">
This email was sent to <a =
href=3D"mailto:sukh@yyy.com" class=3D"">sukh@yyy.com</a>
href=3D"mailto:sukh@example.com" class=3D"">sukh@example.com</a>
<p style=3D"margin: 15px auto;" class=3D"">
<a =
href=3D"http://frappe.xxx.com/api/method/frappe.email.bulk.unsubscribe=
?email=3Dsukh%40yyy.com&amp;name=3DWN-SUP17470&amp;doctype=3DIssue=
href=3D"http://frappe.example.com/api/method/frappe.email.bulk.unsubscribe=
?email=3Dsukh%40example.com&amp;name=3DWN-SUP17470&amp;doctype=3DIssue=
&amp;_signature=3Dbbabf063b4f3aad9ba1af915aa66df23" style=3D"color: =
#8d99a6; text-decoration: underline;
target=3D" _blank"=3D"" =
@ -179,7 +179,7 @@ class=3D"">Leave this conversation
center; color: #8d99a6" class=3D"">Frappe Technologies Private =
Limited</div><div style=3D"margin: 15px auto;" class=3D""><div =
style=3D"text-align: center;" class=3D"">
<a href=3D"https://xxx.com/?source=3Dvia_email_footer" =
<a href=3D"https://example.com/?source=3Dvia_email_footer" =
target=3D"_blank" style=3D"color: #8d99a6;" class=3D"">
Sent via ERPNext
</a>

View file

@ -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):

View file

@ -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)
time.sleep(s)

View file

@ -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:

View file

@ -53,7 +53,6 @@ frappe.ready(function() {
// submit
$(".btn-form-submit").on("click", function() {
let data = frappe.web_form.get_values();
save();
return false;
});