Merge branch 'master' into staging-fixes
This commit is contained in:
commit
fe3fe0a4b8
13 changed files with 127 additions and 85 deletions
|
|
@ -23,7 +23,7 @@ if sys.version[0] == '2':
|
|||
reload(sys)
|
||||
sys.setdefaultencoding("utf-8")
|
||||
|
||||
__version__ = '10.1.70'
|
||||
__version__ = '10.1.71'
|
||||
__title__ = "Frappe Framework"
|
||||
|
||||
local = Local()
|
||||
|
|
|
|||
|
|
@ -571,7 +571,7 @@ def get_version():
|
|||
@click.command('setup-global-help')
|
||||
@click.option('--mariadb_root_password')
|
||||
def setup_global_help(mariadb_root_password=None):
|
||||
'''Removed: setup help table in a separate database that will be
|
||||
'''Deprecated: setup help table in a separate database that will be
|
||||
shared by the whole bench and set `global_help_setup` as 1 in
|
||||
common_site_config.json'''
|
||||
print_in_app_help_deprecation()
|
||||
|
|
@ -579,18 +579,18 @@ def setup_global_help(mariadb_root_password=None):
|
|||
@click.command('get-docs-app')
|
||||
@click.argument('app')
|
||||
def get_docs_app(app):
|
||||
'''Removed: Get the docs app for given app'''
|
||||
'''Deprecated: Get the docs app for given app'''
|
||||
print_in_app_help_deprecation()
|
||||
|
||||
@click.command('get-all-docs-apps')
|
||||
def get_all_docs_apps():
|
||||
'''Removed: Get docs apps for all apps'''
|
||||
'''Deprecated: Get docs apps for all apps'''
|
||||
print_in_app_help_deprecation()
|
||||
|
||||
@click.command('setup-help')
|
||||
@pass_context
|
||||
def setup_help(context):
|
||||
'''Removed: Setup help table in the current site (called after migrate)'''
|
||||
'''Deprecated: Setup help table in the current site (called after migrate)'''
|
||||
print_in_app_help_deprecation()
|
||||
|
||||
@click.command('rebuild-global-search')
|
||||
|
|
@ -686,6 +686,5 @@ commands = [
|
|||
watch,
|
||||
_bulk_rename,
|
||||
add_to_email_queue,
|
||||
rebuild_global_search,
|
||||
auto_deploy
|
||||
rebuild_global_search
|
||||
]
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ frappe.ui.form.on('Custom Field', {
|
|||
frm.set_query('dt', function(doc) {
|
||||
var filters = [
|
||||
['DocType', 'issingle', '=', 0],
|
||||
['DocType', 'custom', '=', 0],
|
||||
['DocType', 'name', 'not in', frappe.model.core_doctypes_list],
|
||||
['DocType', 'restrict_to_domain', 'in', frappe.boot.active_domains]
|
||||
];
|
||||
if(frappe.session.user!=="Administrator") {
|
||||
filters.push(['DocType', 'module', 'not in', ['Core', 'Custom']])
|
||||
|
|
@ -32,15 +35,21 @@ frappe.ui.form.on('Custom Field', {
|
|||
return frappe.call({
|
||||
method: 'frappe.custom.doctype.custom_field.custom_field.get_fields_label',
|
||||
args: { doctype: frm.doc.dt, fieldname: frm.doc.fieldname },
|
||||
callback: function(r, rt) {
|
||||
set_field_options('insert_after', r.message);
|
||||
var fieldnames = $.map(r.message, function(v) { return v.value; });
|
||||
callback: function(r) {
|
||||
if(r) {
|
||||
if(r._server_messages && r._server_messages.length) {
|
||||
frm.set_value("dt", "");
|
||||
} else {
|
||||
set_field_options('insert_after', r.message);
|
||||
var fieldnames = $.map(r.message, function(v) { return v.value; });
|
||||
|
||||
if(insert_after==null || !in_list(fieldnames, insert_after)) {
|
||||
insert_after = fieldnames[-1];
|
||||
if(insert_after==null || !in_list(fieldnames, insert_after)) {
|
||||
insert_after = fieldnames[-1];
|
||||
}
|
||||
|
||||
frm.set_value('insert_after', insert_after);
|
||||
}
|
||||
}
|
||||
|
||||
frm.set_value('insert_after', insert_after);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from frappe.utils import cstr
|
|||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.docfield import supports_translation
|
||||
from frappe.model import core_doctypes_list
|
||||
|
||||
class CustomField(Document):
|
||||
def autoname(self):
|
||||
|
|
@ -86,6 +87,14 @@ class CustomField(Document):
|
|||
|
||||
@frappe.whitelist()
|
||||
def get_fields_label(doctype=None):
|
||||
meta = frappe.get_meta(doctype)
|
||||
|
||||
if doctype in core_doctypes_list:
|
||||
return frappe.msgprint(_("Custom Fields cannot be added to core DocTypes."))
|
||||
|
||||
if meta.custom:
|
||||
return frappe.msgprint(_("Custom Fields can only be added to a standard DocType."))
|
||||
|
||||
return [{"value": df.fieldname or "", "label": _(df.label or "")}
|
||||
for df in frappe.get_meta(doctype).get("fields")]
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ frappe.ui.form.on("Customize Form", {
|
|||
filters: [
|
||||
['DocType', 'issingle', '=', 0],
|
||||
['DocType', 'custom', '=', 0],
|
||||
['DocType', 'name', 'not in', 'DocType, DocField, DocPerm, User, Role, Has Role, \
|
||||
Page, Has Role, Module Def, Print Format, Report, Customize Form, \
|
||||
Customize Form Field, Property Setter, Custom Field, Custom Script'],
|
||||
['DocType', 'name', 'not in', frappe.model.core_doctypes_list],
|
||||
['DocType', 'restrict_to_domain', 'in', frappe.boot.active_domains]
|
||||
]
|
||||
};
|
||||
|
|
@ -39,8 +37,14 @@ frappe.ui.form.on("Customize Form", {
|
|||
doc: frm.doc,
|
||||
freeze: true,
|
||||
callback: function(r) {
|
||||
frm.refresh();
|
||||
frm.trigger("setup_sortable");
|
||||
if(r) {
|
||||
if(r._server_messages && r._server_messages.length) {
|
||||
frm.set_value("doc_type", "");
|
||||
} else {
|
||||
frm.refresh();
|
||||
frm.trigger("setup_sortable");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import frappe.translate
|
|||
from frappe import _
|
||||
from frappe.utils import cint
|
||||
from frappe.model.document import Document
|
||||
from frappe.model import no_value_fields
|
||||
from frappe.model import no_value_fields, core_doctypes_list
|
||||
from frappe.core.doctype.doctype.doctype import validate_fields_for_doctype
|
||||
from frappe.model.docfield import supports_translation
|
||||
|
||||
|
|
@ -85,6 +85,12 @@ class CustomizeForm(Document):
|
|||
|
||||
meta = frappe.get_meta(self.doc_type)
|
||||
|
||||
if self.doc_type in core_doctypes_list:
|
||||
return frappe.msgprint(_("Core DocTypes cannot be customized."))
|
||||
|
||||
if meta.custom:
|
||||
return frappe.msgprint(_("Only standard DocTypes are allowed to be customized from Customize Form."))
|
||||
|
||||
# doctype properties
|
||||
for property in doctype_properties:
|
||||
self.set(property, meta.get(property))
|
||||
|
|
|
|||
|
|
@ -9,28 +9,28 @@ from frappe.core.doctype.doctype.doctype import InvalidFieldNameError
|
|||
test_dependencies = ["Custom Field", "Property Setter"]
|
||||
class TestCustomizeForm(unittest.TestCase):
|
||||
def insert_custom_field(self):
|
||||
frappe.delete_doc_if_exists("Custom Field", "User-test_custom_field")
|
||||
frappe.delete_doc_if_exists("Custom Field", "Event-test_custom_field")
|
||||
frappe.get_doc({
|
||||
"doctype": "Custom Field",
|
||||
"dt": "User",
|
||||
"dt": "Event",
|
||||
"label": "Test Custom Field",
|
||||
"description": "A Custom Field for Testing",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"options": "\nCustom 1\nCustom 2\nCustom 3",
|
||||
"default": "Custom 3",
|
||||
"insert_after": frappe.get_meta('User').fields[-1].fieldname
|
||||
"insert_after": frappe.get_meta('Event').fields[-1].fieldname
|
||||
}).insert()
|
||||
|
||||
def setUp(self):
|
||||
self.insert_custom_field()
|
||||
frappe.db.commit()
|
||||
frappe.clear_cache(doctype="User")
|
||||
frappe.clear_cache(doctype="Event")
|
||||
|
||||
def tearDown(self):
|
||||
frappe.delete_doc("Custom Field", "User-test_custom_field")
|
||||
frappe.delete_doc("Custom Field", "Event-test_custom_field")
|
||||
frappe.db.commit()
|
||||
frappe.clear_cache(doctype="User")
|
||||
frappe.clear_cache(doctype="Event")
|
||||
|
||||
def get_customize_form(self, doctype=None):
|
||||
d = frappe.get_doc("Customize Form")
|
||||
|
|
@ -45,78 +45,67 @@ class TestCustomizeForm(unittest.TestCase):
|
|||
self.assertEqual(len(d.get("fields")), 0)
|
||||
|
||||
d = self.get_customize_form("Event")
|
||||
self.assertEqual(d.doc_type, "Event")
|
||||
self.assertEqual(len(d.get("fields")), 27)
|
||||
self.assertEquals(d.doc_type, "Event")
|
||||
self.assertEquals(len(d.get("fields")), 30)
|
||||
|
||||
d = self.get_customize_form("User")
|
||||
self.assertEqual(d.doc_type, "User")
|
||||
d = self.get_customize_form("Event")
|
||||
self.assertEquals(d.doc_type, "Event")
|
||||
|
||||
self.assertEqual(len(d.get("fields")),
|
||||
len(frappe.get_doc("DocType", d.doc_type).fields) + 1)
|
||||
self.assertEqual(d.get("fields")[-1].fieldname, "test_custom_field")
|
||||
self.assertEqual(d.get("fields", {"fieldname": "location"})[0].in_list_view, 1)
|
||||
self.assertEquals(d.get("fields")[-1].fieldname, "test_custom_field")
|
||||
self.assertEquals(d.get("fields", {"fieldname": "event_type"})[0].in_list_view, 1)
|
||||
|
||||
return d
|
||||
|
||||
def test_save_customization_property(self):
|
||||
d = self.get_customize_form("User")
|
||||
self.assertEqual(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "User", "property": "allow_copy"}, "value"), None)
|
||||
d = self.get_customize_form("Event")
|
||||
self.assertEquals(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "Event", "property": "allow_copy"}, "value"), None)
|
||||
|
||||
d.allow_copy = 1
|
||||
d.run_method("save_customization")
|
||||
self.assertEqual(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "User", "property": "allow_copy"}, "value"), '1')
|
||||
self.assertEquals(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "Event", "property": "allow_copy"}, "value"), '1')
|
||||
|
||||
d.allow_copy = 0
|
||||
d.run_method("save_customization")
|
||||
self.assertEqual(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "User", "property": "allow_copy"}, "value"), None)
|
||||
self.assertEquals(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "Event", "property": "allow_copy"}, "value"), None)
|
||||
|
||||
def test_save_customization_field_property(self):
|
||||
d = self.get_customize_form("User")
|
||||
self.assertEqual(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "User", "property": "reqd", "field_name": "location"}, "value"), None)
|
||||
d = self.get_customize_form("Event")
|
||||
self.assertEquals(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "Event", "property": "reqd", "field_name": "repeat_this_event"}, "value"), None)
|
||||
|
||||
location_field = d.get("fields", {"fieldname": "location"})[0]
|
||||
location_field.reqd = 1
|
||||
repeat_this_event_field = d.get("fields", {"fieldname": "repeat_this_event"})[0]
|
||||
repeat_this_event_field.reqd = 1
|
||||
d.run_method("save_customization")
|
||||
self.assertEqual(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "User", "property": "reqd", "field_name": "location"}, "value"), '1')
|
||||
self.assertEquals(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "Event", "property": "reqd", "field_name": "repeat_this_event"}, "value"), '1')
|
||||
|
||||
location_field = d.get("fields", {"fieldname": "location"})[0]
|
||||
location_field.reqd = 0
|
||||
repeat_this_event_field = d.get("fields", {"fieldname": "repeat_this_event"})[0]
|
||||
repeat_this_event_field.reqd = 0
|
||||
d.run_method("save_customization")
|
||||
self.assertEqual(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "User", "property": "reqd", "field_name": "location"}, "value"), None)
|
||||
|
||||
# for not allowing to change mandatory property of standard fields
|
||||
self.assertEqual(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "User", "property": "reqd", "field_name": "email"}, "value"), None)
|
||||
|
||||
email_field = d.get("fields", {"fieldname": "email"})[0]
|
||||
email_field.reqd = 0
|
||||
d.run_method("save_customization")
|
||||
|
||||
self.assertEqual(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "User", "property": "reqd", "field_name": "email"}, "value"), None)
|
||||
self.assertEquals(frappe.db.get_value("Property Setter",
|
||||
{"doc_type": "Event", "property": "reqd", "field_name": "repeat_this_event"}, "value"), None)
|
||||
|
||||
def test_save_customization_custom_field_property(self):
|
||||
d = self.get_customize_form("User")
|
||||
self.assertEqual(frappe.db.get_value("Custom Field", "User-test_custom_field", "reqd"), 0)
|
||||
d = self.get_customize_form("Event")
|
||||
self.assertEquals(frappe.db.get_value("Custom Field", "Event-test_custom_field", "reqd"), 0)
|
||||
|
||||
custom_field = d.get("fields", {"fieldname": "test_custom_field"})[0]
|
||||
custom_field.reqd = 1
|
||||
d.run_method("save_customization")
|
||||
self.assertEqual(frappe.db.get_value("Custom Field", "User-test_custom_field", "reqd"), 1)
|
||||
self.assertEquals(frappe.db.get_value("Custom Field", "Event-test_custom_field", "reqd"), 1)
|
||||
|
||||
custom_field = d.get("fields", {"is_custom_field": True})[0]
|
||||
custom_field.reqd = 0
|
||||
d.run_method("save_customization")
|
||||
self.assertEqual(frappe.db.get_value("Custom Field", "User-test_custom_field", "reqd"), 0)
|
||||
self.assertEquals(frappe.db.get_value("Custom Field", "Event-test_custom_field", "reqd"), 0)
|
||||
|
||||
def test_save_customization_new_field(self):
|
||||
d = self.get_customize_form("User")
|
||||
d = self.get_customize_form("Event")
|
||||
last_fieldname = d.fields[-1].fieldname
|
||||
d.append("fields", {
|
||||
"label": "Test Add Custom Field Via Customize Form",
|
||||
|
|
@ -124,19 +113,19 @@ class TestCustomizeForm(unittest.TestCase):
|
|||
"is_custom_field": 1
|
||||
})
|
||||
d.run_method("save_customization")
|
||||
self.assertEqual(frappe.db.get_value("Custom Field",
|
||||
"User-test_add_custom_field_via_customize_form", "fieldtype"), "Data")
|
||||
self.assertEquals(frappe.db.get_value("Custom Field",
|
||||
"Event-test_add_custom_field_via_customize_form", "fieldtype"), "Data")
|
||||
|
||||
self.assertEqual(frappe.db.get_value("Custom Field",
|
||||
"User-test_add_custom_field_via_customize_form", 'insert_after'), last_fieldname)
|
||||
self.assertEquals(frappe.db.get_value("Custom Field",
|
||||
"Event-test_add_custom_field_via_customize_form", 'insert_after'), last_fieldname)
|
||||
|
||||
frappe.delete_doc("Custom Field", "User-test_add_custom_field_via_customize_form")
|
||||
self.assertEqual(frappe.db.get_value("Custom Field",
|
||||
"User-test_add_custom_field_via_customize_form"), None)
|
||||
frappe.delete_doc("Custom Field", "Event-test_add_custom_field_via_customize_form")
|
||||
self.assertEquals(frappe.db.get_value("Custom Field",
|
||||
"Event-test_add_custom_field_via_customize_form"), None)
|
||||
|
||||
|
||||
def test_save_customization_remove_field(self):
|
||||
d = self.get_customize_form("User")
|
||||
d = self.get_customize_form("Event")
|
||||
custom_field = d.get("fields", {"fieldname": "test_custom_field"})[0]
|
||||
d.get("fields").remove(custom_field)
|
||||
d.run_method("save_customization")
|
||||
|
|
@ -148,24 +137,24 @@ class TestCustomizeForm(unittest.TestCase):
|
|||
|
||||
def test_reset_to_defaults(self):
|
||||
d = frappe.get_doc("Customize Form")
|
||||
d.doc_type = "User"
|
||||
d.doc_type = "Event"
|
||||
d.run_method('reset_to_defaults')
|
||||
|
||||
self.assertEqual(d.get("fields", {"fieldname": "location"})[0].in_list_view, 0)
|
||||
self.assertEquals(d.get("fields", {"fieldname": "repeat_this_event"})[0].in_list_view, 0)
|
||||
|
||||
frappe.local.test_objects["Property Setter"] = []
|
||||
make_test_records_for_doctype("Property Setter")
|
||||
|
||||
def test_set_allow_on_submit(self):
|
||||
d = self.get_customize_form("User")
|
||||
d.get("fields", {"fieldname": "first_name"})[0].allow_on_submit = 1
|
||||
d = self.get_customize_form("Event")
|
||||
d.get("fields", {"fieldname": "subject"})[0].allow_on_submit = 1
|
||||
d.get("fields", {"fieldname": "test_custom_field"})[0].allow_on_submit = 1
|
||||
d.run_method("save_customization")
|
||||
|
||||
d = self.get_customize_form("User")
|
||||
d = self.get_customize_form("Event")
|
||||
|
||||
# don't allow for standard fields
|
||||
self.assertEqual(d.get("fields", {"fieldname": "first_name"})[0].allow_on_submit or 0, 0)
|
||||
self.assertEquals(d.get("fields", {"fieldname": "subject"})[0].allow_on_submit or 0, 0)
|
||||
|
||||
# allow for custom field
|
||||
self.assertEqual(d.get("fields", {"fieldname": "test_custom_field"})[0].allow_on_submit, 1)
|
||||
|
|
@ -193,4 +182,12 @@ class TestCustomizeForm(unittest.TestCase):
|
|||
|
||||
# undo
|
||||
df.default = None
|
||||
d.run_method("save_customization")
|
||||
d.run_method("save_customization")
|
||||
|
||||
def test_core_doctype_customization(self):
|
||||
d = self.get_customize_form('User')
|
||||
e = self.get_customize_form('Custom Field')
|
||||
|
||||
# core doctype is invalid, hence no attributes are set
|
||||
self.assertEquals(d.get("fields"), [])
|
||||
self.assertEquals(e.get("fields"), [])
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ display_fieldtypes = ('Section Break', 'Column Break', 'HTML', 'Button', 'Image'
|
|||
default_fields = ('doctype','name','owner','creation','modified','modified_by',
|
||||
'parent','parentfield','parenttype','idx','docstatus')
|
||||
optional_fields = ("_user_tags", "_comments", "_assign", "_liked_by", "_seen")
|
||||
core_doctypes_list = ('DocType', 'DocField', 'DocPerm', 'User', 'Role', 'Has Role',
|
||||
'Page', 'Module Def', 'Print Format', 'Report', 'Customize Form',
|
||||
'Customize Form Field', 'Property Setter', 'Custom Field', 'Custom Script')
|
||||
|
||||
def copytables(srctype, src, srcfield, tartype, tar, tarfield, srcfields, tarfields=[]):
|
||||
if not tarfields:
|
||||
|
|
|
|||
|
|
@ -504,6 +504,9 @@ frappe.ui.form.Layout = Class.extend({
|
|||
} else if(expression.substr(0,5)=='eval:') {
|
||||
try {
|
||||
out = eval(expression.substr(5));
|
||||
if(parent && parent.istable && expression.includes('is_submittable')) {
|
||||
out = true;
|
||||
}
|
||||
} catch(e) {
|
||||
frappe.throw(__('Invalid "depends_on" expression'));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -971,9 +971,13 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
|
|||
|
||||
items.push({
|
||||
label: __('Customize'),
|
||||
action: () => frappe.set_route('Form', 'Customize Form', {
|
||||
doc_type: doctype
|
||||
}),
|
||||
action: () => {
|
||||
if(this.meta && !this.meta.custom) {
|
||||
frappe.set_route('Form', 'Customize Form', {
|
||||
doc_type: doctype
|
||||
});
|
||||
}
|
||||
},
|
||||
standard: true
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ $.extend(frappe.model, {
|
|||
'_user_tags', '_comments', '_assign', '_liked_by', 'docstatus',
|
||||
'parent', 'parenttype', 'parentfield', 'idx'],
|
||||
|
||||
core_doctypes_list: ['DocType', 'DocField', 'DocPerm', 'User', 'Role', 'Has Role',
|
||||
'Page', 'Module Def', 'Print Format', 'Report', 'Customize Form',
|
||||
'Customize Form Field', 'Property Setter', 'Custom Field', 'Custom Script'],
|
||||
|
||||
std_fields: [
|
||||
{fieldname:'name', fieldtype:'Link', label:__('ID')},
|
||||
{fieldname:'owner', fieldtype:'Link', label:__('Created By'), options: 'User'},
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ frappe.ui.toolbar.Toolbar = Class.extend({
|
|||
|
||||
$("#input-help").on("keydown", function (e) {
|
||||
if(e.which == 13) {
|
||||
var keywords = $(this).val();
|
||||
$(this).val("");
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@ def get_pdf(html, options=None, output = None):
|
|||
html, options = prepare_options(html, options)
|
||||
fname = os.path.join("/tmp", "frappe-pdf-{0}.pdf".format(frappe.generate_hash()))
|
||||
|
||||
options.update({
|
||||
"disable-javascript": "",
|
||||
"disable-local-file-access": "",
|
||||
})
|
||||
|
||||
try:
|
||||
pdfkit.from_string(html, fname, options=options or {})
|
||||
if output:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue