diff --git a/frappe/__init__.py b/frappe/__init__.py
index 990af664e4..280bd480b7 100644
--- a/frappe/__init__.py
+++ b/frappe/__init__.py
@@ -13,7 +13,7 @@ import os, sys, importlib, inspect, json
from .exceptions import *
from .utils.jinja import get_jenv, get_template, render_template
-__version__ = '7.1.10'
+__version__ = '7.1.11'
__title__ = "Frappe Framework"
local = Local()
diff --git a/frappe/api.py b/frappe/api.py
index 0092067ffb..afdc3b8630 100644
--- a/frappe/api.py
+++ b/frappe/api.py
@@ -10,7 +10,6 @@ from frappe.utils.response import build_response
from frappe import _
from urlparse import urlparse
from urllib import urlencode
-from frappe.integration_broker.oauth2 import oauth_server
def handle():
"""
@@ -36,25 +35,7 @@ def handle():
`/api/resource/{doctype}/{name}?run_method={method}` will run a whitelisted controller method
"""
- form_dict = frappe.local.form_dict
- authorization_header = frappe.get_request_header("Authorization").split(" ") if frappe.get_request_header("Authorization") else None
- if authorization_header and authorization_header[0].lower() == "bearer":
- token = authorization_header[1]
- r = frappe.request
- parsed_url = urlparse(r.url)
- access_token = { "access_token": token}
- uri = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path + "?" + urlencode(access_token)
- http_method = r.method
- body = r.get_data()
- headers = r.headers
-
- required_scopes = frappe.db.get_value("OAuth Bearer Token", token, "scopes").split(";")
-
- valid, oauthlib_request = oauth_server.verify_request(uri, http_method, body, headers, required_scopes)
-
- if valid:
- frappe.set_user(frappe.db.get_value("OAuth Bearer Token", token, "user"))
- frappe.local.form_dict = form_dict
+ validate_oauth()
parts = frappe.request.path[1:].split("/",3)
call = doctype = name = None
@@ -146,3 +127,25 @@ def handle():
raise frappe.DoesNotExistError
return build_response("json")
+
+def validate_oauth():
+ form_dict = frappe.local.form_dict
+ authorization_header = frappe.get_request_header("Authorization").split(" ") if frappe.get_request_header("Authorization") else None
+ if authorization_header and authorization_header[0].lower() == "bearer":
+ from frappe.integration_broker.oauth2 import get_oauth_server
+ token = authorization_header[1]
+ r = frappe.request
+ parsed_url = urlparse(r.url)
+ access_token = { "access_token": token}
+ uri = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path + "?" + urlencode(access_token)
+ http_method = r.method
+ body = r.get_data()
+ headers = r.headers
+
+ required_scopes = frappe.db.get_value("OAuth Bearer Token", token, "scopes").split(";")
+
+ valid, oauthlib_request = get_oauth_server().verify_request(uri, http_method, body, headers, required_scopes)
+
+ if valid:
+ frappe.set_user(frappe.db.get_value("OAuth Bearer Token", token, "user"))
+ frappe.local.form_dict = form_dict
diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py
index c5505b1b13..a5dfeafb6c 100644
--- a/frappe/core/doctype/report/report.py
+++ b/frappe/core/doctype/report/report.py
@@ -57,7 +57,14 @@ class Report(Document):
if self.report_type in ('Query Report', 'Script Report'):
# query and script reports
data = frappe.desk.query_report.run(self.name, filters=filters, user=user)
- out.append([d.split(':')[0] for d in data.get('columns')])
+ columns_list = []
+ for d in data.get('columns'):
+ if isinstance(d, dict):
+ columns_list.append(d.get('label'))
+ else:
+ columns_list.append(d.split(':')[0])
+
+ out.append(columns_list)
out += data.get('result')
else:
# standard report
diff --git a/frappe/email/doctype/auto_email_report/auto_email_report.js b/frappe/email/doctype/auto_email_report/auto_email_report.js
index f01fec1c76..456ddff18f 100644
--- a/frappe/email/doctype/auto_email_report/auto_email_report.js
+++ b/frappe/email/doctype/auto_email_report/auto_email_report.js
@@ -60,9 +60,19 @@ frappe.ui.form.on('Auto Email Report', {
'+__('Filter')+' | '+__('Value')+' |
\
').appendTo(wrapper);
$('' + __("Click table to edit") + '
').appendTo(wrapper);
+
var filters = JSON.parse(frm.doc.filters || '{}');
var report_filters = frappe.query_reports[frm.doc.report].filters;
+ report_filters_list = []
+ $.each(report_filters, function(key, val){
+ // Remove break fieldtype from the filters
+ if(val.fieldtype != 'Break') {
+ report_filters_list.push(val)
+ }
+ })
+ report_filters = report_filters_list;
+
report_filters.forEach(function(f) {
$('' + f.label + ' | '+ frappe.format(filters[f.fieldname], f) +' |
')
.appendTo(table.find('tbody'));
diff --git a/frappe/integration_broker/oauth2.py b/frappe/integration_broker/oauth2.py
index 422b6c9d4e..ed48b83a4c 100644
--- a/frappe/integration_broker/oauth2.py
+++ b/frappe/integration_broker/oauth2.py
@@ -6,10 +6,12 @@ from urllib import quote, urlencode
from urlparse import urlparse
from frappe.integrations.doctype.oauth_provider_settings.oauth_provider_settings import get_oauth_settings
-#Variables required across requests
-oauth_validator = OAuthWebRequestValidator()
-oauth_server = WebApplicationServer(oauth_validator)
-credentials = None
+def get_oauth_server():
+ if not getattr(frappe.local, 'oauth_server', None):
+ oauth_validator = OAuthWebRequestValidator()
+ frappe.local.oauth_server = WebApplicationServer(oauth_validator)
+
+ return frappe.local.oauth_server
def get_urlparams_from_kwargs(param_kwargs):
arguments = param_kwargs
@@ -29,10 +31,10 @@ def approve(*args, **kwargs):
headers = r.headers
try:
- scopes, credentials = oauth_server.validate_authorization_request(uri, http_method, body, headers)
+ scopes, frappe.flags.oauth_credentials = get_oauth_server().validate_authorization_request(uri, http_method, body, headers)
- headers, body, status = oauth_server.create_authorization_response(uri=credentials['redirect_uri'], \
- body=body, headers=headers, scopes=scopes, credentials=credentials)
+ headers, body, status = get_oauth_server().create_authorization_response(uri=frappe.flags.oauth_credentials['redirect_uri'], \
+ body=body, headers=headers, scopes=scopes, credentials=frappe.flags.oauth_credentials)
uri = headers.get('Location', None)
frappe.local.response["type"] = "redirect"
@@ -50,7 +52,7 @@ def authorize(*args, **kwargs):
params = get_urlparams_from_kwargs(kwargs)
request_url = urlparse(frappe.request.url)
success_url = request_url.scheme + "://" + request_url.netloc + "/api/method/frappe.integration_broker.oauth2.approve?" + params
- failure_url = frappe.form_dict["redirect_uri"] + "?error=access_denied"
+ failure_url = frappe.form_dict["redirect_uri"] + "?error=access_denied"
if frappe.session['user']=='Guest':
#Force login, redirect to preauth again.
@@ -65,9 +67,9 @@ def authorize(*args, **kwargs):
body = r.get_data()
headers = r.headers
- scopes, credentials = oauth_server.validate_authorization_request(uri, http_method, body, headers)
+ scopes, frappe.flags.oauth_credentials = get_oauth_server().validate_authorization_request(uri, http_method, body, headers)
- skip_auth = frappe.db.get_value("OAuth Client", credentials['client_id'], "skip_authorization")
+ skip_auth = frappe.db.get_value("OAuth Client", frappe.flags.oauth_credentials['client_id'], "skip_authorization")
unrevoked_tokens = frappe.get_all("OAuth Bearer Token", filters={"status":"Active"})
if skip_auth or (oauth_settings["skip_authorization"] == "Auto" and len(unrevoked_tokens)):
@@ -100,7 +102,7 @@ def get_token(*args, **kwargs):
headers = r.headers
try:
- headers, body, status = oauth_server.create_token_response(uri, http_method, body, headers, credentials)
+ headers, body, status = get_oauth_server().create_token_response(uri, http_method, body, headers, frappe.flags.oauth_credentials)
frappe.local.response = frappe._dict(json.loads(body))
except FatalClientError as e:
return e
@@ -113,9 +115,9 @@ def revoke_token(*args, **kwargs):
http_method = r.method
body = r.form
headers = r.headers
-
- headers, body, status = oauth_server.create_revocation_response(uri, headers=headers, body=body, http_method=http_method)
-
+
+ headers, body, status = get_oauth_server().create_revocation_response(uri, headers=headers, body=body, http_method=http_method)
+
frappe.local.response['http_status_code'] = status
if status == 200:
return "success"
diff --git a/frappe/public/css/desk.css b/frappe/public/css/desk.css
index 7b5149f542..e45d440ba6 100644
--- a/frappe/public/css/desk.css
+++ b/frappe/public/css/desk.css
@@ -355,7 +355,7 @@ fieldset[disabled] .form-control {
}
/* jquery ui */
.ui-datepicker {
- z-index: 100 !important;
+ z-index: 9999 !important;
}
.ui-datepicker .ui-datepicker-header {
border-radius: 0px !important;
diff --git a/frappe/public/js/frappe/list/doclistview.js b/frappe/public/js/frappe/list/doclistview.js
index 3662994560..d5bc5818d7 100644
--- a/frappe/public/js/frappe/list/doclistview.js
+++ b/frappe/public/js/frappe/list/doclistview.js
@@ -781,13 +781,19 @@ frappe.views.DocListView = frappe.ui.Listing.extend({
toggle_delete: function() {
var me = this;
- if (this.$page.find(".list-delete:checked").length) {
+ var no_of_checked_items = this.$page.find(".list-delete:checked").length;
+ if (no_of_checked_items) {
this.page.set_primary_action(__("Delete"), function() { me.delete_items() },
"octicon octicon-trashcan");
this.page.btn_primary.addClass("btn-danger");
+ this.page.checked_items_status.text(no_of_checked_items == 1
+ ? __("1 item selected")
+ : __("{0} items selected", [no_of_checked_items]))
+ this.page.checked_items_status.removeClass("hide");
} else {
this.page.btn_primary.removeClass("btn-danger");
this.set_primary_action();
+ this.page.checked_items_status.addClass("hide");
}
},
diff --git a/frappe/public/js/frappe/ui/page.html b/frappe/public/js/frappe/ui/page.html
index 1b378f5574..f3ad393657 100644
--- a/frappe/public/js/frappe/ui/page.html
+++ b/frappe/public/js/frappe/ui/page.html
@@ -12,6 +12,7 @@
+ ## items selected
diff --git a/frappe/public/js/frappe/ui/page.js b/frappe/public/js/frappe/ui/page.js
index 0439f5b4ae..685384ce57 100644
--- a/frappe/public/js/frappe/ui/page.js
+++ b/frappe/public/js/frappe/ui/page.js
@@ -80,6 +80,7 @@ frappe.ui.Page = Class.extend({
this.page_actions = this.wrapper.find(".page-actions");
+ this.checked_items_status = this.page_actions.find(".checked-items-status");
this.btn_primary = this.page_actions.find(".primary-action");
this.btn_secondary = this.page_actions.find(".btn-secondary");
diff --git a/frappe/public/less/desk.less b/frappe/public/less/desk.less
index c3fb6bc098..ffcdcbce18 100644
--- a/frappe/public/less/desk.less
+++ b/frappe/public/less/desk.less
@@ -146,7 +146,7 @@ textarea.form-control {
/* jquery ui */
.ui-datepicker {
- z-index: 100 !important;
+ z-index: 9999 !important;
}
.ui-datepicker .ui-datepicker-header {