Merge branch 'staging' into develop

This commit is contained in:
Saurabh 2019-01-01 14:26:16 +05:30
commit d5fdc670f7
14 changed files with 92 additions and 71 deletions

View file

@ -8,7 +8,6 @@ import json
from frappe import _
from frappe.model.document import Document
from six import iteritems
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
class KanbanBoard(Document):
@ -130,17 +129,8 @@ def update_order(board_name, order):
@frappe.whitelist()
def quick_kanban_board(doctype, board_name, field_name, project=None):
'''Create new KanbanBoard quickly with default options'''
doc = frappe.new_doc('Kanban Board')
if field_name == 'kanban_column':
create_custom_field(doctype, {
'label': 'Kanban Column',
'fieldname': 'kanban_column',
'fieldtype': 'Select',
'hidden': 1,
'owner': 'Administrator'
})
meta = frappe.get_meta(doctype)
options = ''

View file

@ -12,7 +12,7 @@ source_link = "https://github.com/frappe/frappe"
app_license = "MIT"
develop_version = '12.x.x-develop'
staging_version = '11.0.3-beta.45'
staging_version = '11.0.3-beta.46'
app_email = "info@frappe.io"

View file

@ -573,6 +573,7 @@ class DatabaseQuery(object):
)
match_conditions.append("({condition})".format(condition=condition))
match_filters[df.get('options')] = docs
if match_conditions:
self.match_conditions.append(" and ".join(match_conditions))

View file

@ -220,7 +220,7 @@ def check_if_doc_is_linked(doc, method="Delete"):
def check_if_doc_is_dynamically_linked(doc, method="Delete"):
'''Raise `frappe.LinkExistsError` if the document is dynamically linked'''
for df in get_dynamic_link_map().get(doc.doctype, []):
if df.parent in ("Communication", "ToDo", "DocShare", "Email Unsubscribe", "Activity Log", 'File', 'Version'):
if df.parent in ("Communication", "ToDo", "DocShare", "Email Unsubscribe", "Activity Log", 'File', 'Version', 'View log'):
# don't check for communication and todo!
continue
@ -286,6 +286,10 @@ def delete_dynamic_links(doctype, name):
communication_type = 'Comment'
and reference_doctype=%s and reference_name=%s""", (doctype, name))
# delete view logs
frappe.db.sql("""delete from `tabView log`
where reference_doctype=%s and reference_name=%s""", (doctype, name))
# unlink communications
frappe.db.sql("""update `tabCommunication`
set reference_doctype=null, reference_name=null

View file

@ -8,9 +8,11 @@ frappe.defaults = {
if(!d && frappe.defaults.is_a_user_permission_key(key))
d = defaults[frappe.model.scrub(key)];
if($.isArray(d)) d = d[0];
if(frappe.defaults.not_in_user_permission(key, d)) {
if(!frappe.defaults.in_user_permission(key, d)) {
return;
}
return d;
},
get_user_defaults: function(key) {
@ -29,7 +31,7 @@ frappe.defaults = {
// filter out values which are not permitted to the user
d.filter(item => {
if(!frappe.defaults.not_in_user_permission(key, item)) {
if(frappe.defaults.in_user_permission(key, item)) {
return item;
}
});
@ -73,7 +75,7 @@ frappe.defaults = {
}
}
if(frappe.defaults.not_in_user_permission(key, value)) {
if(!frappe.defaults.in_user_permission(key, value)) {
return;
}
@ -90,14 +92,22 @@ frappe.defaults = {
return key.indexOf(":")===-1 && key !== frappe.model.scrub(key);
},
not_in_user_permission: function(key, value) {
let user_permission = this.get_user_permissions()[frappe.model.unscrub(key)] || [];
in_user_permission: function(key, value) {
let user_permission = this.get_user_permissions()[frappe.model.unscrub(key)];
let doc_found = user_permission.some(perm => {
return perm.doc === value;
});
if (user_permission && user_permission.length) {
let doc_found = user_permission.some(perm => {
return perm.doc === value;
});
return doc_found;
} else {
// there is no user permission for this doctype
// so we can allow this doc i.e., value
return true;
}
return !doc_found;
},
get_user_permissions: function() {

View file

@ -150,7 +150,7 @@ frappe.ui.form.AssignToDialog = Class.extend({
{value:'High', label:__('High')}],
'default':'Medium'},
],
primary_action: function() { frappe.ui.add_assignment(opts, me) },
primary_action: function() { frappe.ui.add_assignment(opts, this) },
primary_action_label: __("Add")
})
$.extend(me, dialog);

View file

@ -225,21 +225,18 @@ frappe.views.KanbanView.setup_dropdown_in_sidebar = function(doctype, $dropdown)
const fields = get_fields_for_dialog();
let primary_action_label = fields.length > 1 ? __('Save') : '';
let primary_action = fields.length > 1 ?
({ board_name, field_name, project }) => {
make_kanban_board(board_name, field_name, project)
.then(() => dialog.hide(), (err) => frappe.msgprint(err));
} : null;
dialog = new frappe.ui.Dialog({
title: __('New Kanban Board'),
fields: fields,
primary_action_label: __('Save'),
primary_action(values) {
const custom_column =
values.custom_column !== undefined ?
values.custom_column : 1;
let field_name = custom_column ? 'kanban_column' : values.field_name;
make_kanban_board(values.board_name, field_name, values.project)
.then(() => dialog.hide(), (err) => frappe.msgprint(err));
}
fields,
primary_action_label,
primary_action
});
return dialog;
}
@ -272,26 +269,28 @@ frappe.views.KanbanView.setup_dropdown_in_sidebar = function(doctype, $dropdown)
});
if (select_fields.length > 0) {
fields = fields.concat([{
fields.push({
fieldtype: 'Select',
fieldname: 'field_name',
label: __('Columns based on'),
options: select_fields.map(df => ({label: df.label, value: df.fieldname})),
default: select_fields[0],
depends_on: 'eval:doc.custom_column===0',
reqd: 1
},
{
fieldtype: 'Check',
fieldname: 'custom_column',
label: __('Custom Column'),
default: 0,
onchange() {
const value = this.get_value();
this.layout.set_df_property('field_name', 'reqd', !value);
}
}]);
reqd: 1,
});
} else {
fields = [{
fieldtype: 'HTML',
options: `
<div>
<p class="text-medium">
${__('No fields found that can be used as a Kanban Column. Use the Customize Form to add a Custom Field of type "Select".')}
</p>
<a class="btn btn-xs btn-default" href="#Form/Customize Form?doc_type=${doctype}">
${__('Customize Form')}
</a>
</div>
`
}];
}
return fields;

View file

@ -833,7 +833,13 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
editable,
align,
format: (value, row, column, data) => {
return frappe.format(value, column.docfield, { always_show_decimals: true }, data);
const d = row.reduce((acc, curr) => {
if (!curr.column.docfield) return acc;
acc[curr.column.docfield.fieldname] = curr.content;
return acc;
}, {});
return frappe.format(value, column.docfield, { always_show_decimals: true }, d);
}
};
}
@ -1055,7 +1061,7 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
for (let cdt in values) {
fields = fields.concat(values[cdt].map(f => [f, cdt]));
}
// always keep name (ID) column
this.fields = [["name", this.doctype], ...fields];

View file

@ -13,45 +13,47 @@ def set_request(**kwargs):
class TestWebsite(unittest.TestCase):
def test_page_load(self):
frappe.set_user('Guest')
set_request(method='POST', path='login')
response = render.render()
self.assertTrue(response.status_code, 200)
self.assertEquals(response.status_code, 200)
html = frappe.safe_decode(response.get_data())
self.assertTrue('/* login-css */' in html)
self.assertTrue('// login.js' in html)
self.assertTrue('<!-- login.html -->' in html)
frappe.set_user('Administrator')
def test_redirect(self):
import frappe.hooks
frappe.hooks.website_redirects = [
dict(source='/testfrom', target='://testto1'),
dict(source='/testfromregex.*', target='://testto2'),
dict(source='/testsub/(.*)', target='://testto3/\1')
dict(source=r'/testfrom', target=r'://testto1'),
dict(source=r'/testfromregex.*', target=r'://testto2'),
dict(source=r'/testsub/(.*)', target=r'://testto3/\1')
]
frappe.cache().delete_key('app_hooks')
frappe.cache().delete_key('website_redirects')
set_request(method='GET', path='/testfrom')
response = render.render()
self.assertTrue(response.status_code, 301)
self.assertTrue(response.headers.get('Location'), '://testto1')
self.assertEquals(response.status_code, 301)
self.assertEquals(response.headers.get('Location'), r'://testto1')
set_request(method='GET', path='/testfromregex/test')
response = render.render()
self.assertTrue(response.status_code, 301)
self.assertTrue(response.headers.get('Location'), '://testto2')
self.assertEquals(response.status_code, 301)
self.assertEquals(response.headers.get('Location'), r'://testto2')
set_request(method='GET', path='/testsub/me')
response = render.render()
self.assertTrue(response.status_code, 301)
self.assertTrue(response.headers.get('Location'), '://testto3/me')
self.assertEquals(response.status_code, 301)
self.assertEquals(response.headers.get('Location'), r'://testto3/me')
set_request(method='GET', path='/test404')
response = render.render()
self.assertTrue(response.status_code, 404)
self.assertEquals(response.status_code, 404)
delattr(frappe.hooks, 'website_redirects')
frappe.cache().delete_key('app_hooks')

View file

@ -48,7 +48,7 @@ def update_controller_context(context, controller):
ret = module.get_context(context)
if ret:
context.update(ret)
except (frappe.PermissionError, frappe.DoesNotExistError):
except (frappe.PermissionError, frappe.DoesNotExistError, frappe.Redirect):
raise
except:
if not frappe.flags.in_migrate:

View file

@ -16,7 +16,8 @@ def resolve_redirect(path):
{"source": "/from", "target": "/main"},
# use regex
{"source": "/from/(.*)", "target": "/main/\1"}
{"source": r"/from/(.*)", "target": r"/main/\1"}
# use r as a string prefix if you use regex groups or want to escape any string literal
]
'''
redirects = frappe.get_hooks('website_redirects')
@ -31,7 +32,7 @@ def resolve_redirect(path):
for rule in redirects:
pattern = rule['source'].strip('/ ') + '$'
if re.match(pattern, path):
redirect_to = re.sub(pattern, rule['target'].replace('\\', '\\\\'), path)
redirect_to = re.sub(pattern, rule['target'], path)
frappe.flags.redirect_location = redirect_to
frappe.cache().hset('website_redirects', path, redirect_to)
raise frappe.Redirect

View file

@ -67,6 +67,9 @@ def render(path=None, http_status_code=None):
except frappe.PermissionError as e:
data, http_status_code = render_403(e, path)
except frappe.Redirect as e:
raise e
except Exception:
path = "error"
data = render_page(path)

View file

@ -70,8 +70,13 @@ def get_desk_assets(build_version):
pass
for path in data["include_css"]:
with open(os.path.join(frappe.local.sites_path, path) ,"r") as f:
assets[1]["data"] = assets[1]["data"] + "\n" + frappe.safe_decode(f.read(), "utf-8")
if path.startswith('/assets/'):
path = path.replace('/assets/', 'assets/')
try:
with open(os.path.join(frappe.local.sites_path, path) ,"r") as f:
assets[1]["data"] = assets[1]["data"] + "\n" + frappe.safe_decode(f.read(), "utf-8")
except IOError:
pass
return {
"build_version": data["build_version"],

View file

@ -15,8 +15,8 @@ from frappe.utils.html_utils import get_icon_html
no_cache = True
def get_context(context):
if frappe.session.user != "Guest" and frappe.session.data.user_type=="System User":
frappe.local.flags.redirect_location = "/desk"
if frappe.session.user != "Guest":
frappe.local.flags.redirect_location = "/" if frappe.session.data.user_type=="Website User" else "/desk"
raise frappe.Redirect
# get settings from site config