diff --git a/frappe/__init__.py b/frappe/__init__.py index d403e1026a8..9eeb7ccffcb 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -23,7 +23,7 @@ reload(sys) sys.setdefaultencoding("utf-8") -__version__ = '12.22.2' +__version__ = '12.23.0' __title__ = "Frappe Framework" local = Local() diff --git a/frappe/change_log/v12/v12_23_0.md b/frappe/change_log/v12/v12_23_0.md new file mode 100644 index 00000000000..b19595ffb64 --- /dev/null +++ b/frappe/change_log/v12/v12_23_0.md @@ -0,0 +1,7 @@ +## Frappe Version 12.23.0 Release Notes + +### Fixes & Enhancements + +- Shift+tab keyboard navigation ([#14243](https://github.com/frappe/frappe/pull/14243)) +- Include space and tab in special characters to match to encode url ([#12632](https://github.com/frappe/frappe/pull/12632)) +- `convert_dates_to_str` converts everything except `date` objects ([#14340](https://github.com/frappe/frappe/pull/14340)) \ No newline at end of file diff --git a/frappe/client.py b/frappe/client.py index b24642b70fb..7d77e15b0c4 100644 --- a/frappe/client.py +++ b/frappe/client.py @@ -264,18 +264,17 @@ def bulk_update(docs): docs = json.loads(docs) failed_docs = [] for doc in docs: + doc.pop("flags", None) try: - ddoc = {key: val for key, val in iteritems(doc) if key not in ['doctype', 'docname']} - doctype = doc['doctype'] - docname = doc['docname'] - doc = frappe.get_doc(doctype, docname) - doc.update(ddoc) - doc.save() - except: + existing_doc = frappe.get_doc(doc.pop("doctype"), doc.pop("docname")) + existing_doc.update(doc) + existing_doc.save() + except Exception: failed_docs.append({ 'doc': doc, 'exc': frappe.utils.get_traceback() }) + return {'failed_docs': failed_docs} @frappe.whitelist() @@ -399,4 +398,4 @@ def is_document_amended(doctype, docname): except frappe.db.InternalError: pass - return False \ No newline at end of file + return False diff --git a/frappe/core/doctype/user/user.json b/frappe/core/doctype/user/user.json index b71c9555e17..04d3b0f1c10 100644 --- a/frappe/core/doctype/user/user.json +++ b/frappe/core/doctype/user/user.json @@ -201,7 +201,8 @@ "fieldname": "role_profile_name", "fieldtype": "Link", "label": "Role Profile", - "options": "Role Profile" + "options": "Role Profile", + "permlevel": 1 }, { "fieldname": "roles_html", @@ -586,7 +587,7 @@ "idx": 413, "image_field": "user_image", "max_attachments": 5, - "modified": "2019-10-22 14:16:34.810223", + "modified": "2021-10-18 16:56:05.578379", "modified_by": "Administrator", "module": "Core", "name": "User", @@ -620,4 +621,4 @@ "sort_order": "DESC", "title_field": "full_name", "track_changes": 1 -} \ No newline at end of file +} diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 50ed18e695a..3cd534457d7 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -234,7 +234,12 @@ def get_valid_dict(self, sanitize=True, convert_dates_to_str=False, ignore_nulls if isinstance(d[fieldname], list) and df.fieldtype not in table_fields: frappe.throw(_('Value for {0} cannot be a list').format(_(df.label))) - if convert_dates_to_str and isinstance(d[fieldname], (datetime.datetime, datetime.time, datetime.timedelta)): + if convert_dates_to_str and isinstance(d[fieldname], ( + datetime.datetime, + datetime.date, + datetime.time, + datetime.timedelta + )): d[fieldname] = str(d[fieldname]) if d[fieldname] == None and ignore_nulls: diff --git a/frappe/public/js/frappe/form/layout.js b/frappe/public/js/frappe/form/layout.js index 48da38c82c1..5f5a94fbff8 100644 --- a/frappe/public/js/frappe/form/layout.js +++ b/frappe/public/js/frappe/form/layout.js @@ -396,7 +396,8 @@ frappe.ui.form.Layout = Class.extend({ // next row grid_row.grid.grid_rows[grid_row.doc.idx].toggle_view(true); } - } else { + } else if (!shift) { + // End of tab navigation $(this.primary_button).focus(); } } diff --git a/frappe/public/js/frappe/router.js b/frappe/public/js/frappe/router.js index d60a0c9d7c6..8d00ceef6c7 100644 --- a/frappe/public/js/frappe/router.js +++ b/frappe/public/js/frappe/router.js @@ -160,7 +160,7 @@ frappe.set_route = function() { return null; } else { a = String(a); - if (a && a.match(/[%'"]/)) { + if (a && !a.includes('/') && a.match(/[%'"\s\t]/)) { // if special chars, then encode a = encodeURIComponent(a); } diff --git a/frappe/public/js/frappe/views/communication.js b/frappe/public/js/frappe/views/communication.js index 59f12f2d052..a5749b636a8 100755 --- a/frappe/public/js/frappe/views/communication.js +++ b/frappe/public/js/frappe/views/communication.js @@ -172,6 +172,7 @@ frappe.views.CommunicationComposer = Class.extend({ this.dialog.fields_dict["email_template"].df.onchange = () => { var email_template = me.dialog.fields_dict.email_template.get_value(); + if (!email_template) return; var prepend_reply = function(reply) { if(me.reply_added===email_template) {