diff --git a/frappe/__init__.py b/frappe/__init__.py index bb20fb2354..f049e8b85c 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -14,7 +14,7 @@ import os, sys, importlib, inspect, json from .exceptions import * from .utils.jinja import get_jenv, get_template, render_template, get_email_from_template -__version__ = '9.0.6' +__version__ = '9.0.7' __title__ = "Frappe Framework" local = Local() diff --git a/frappe/model/document.py b/frappe/model/document.py index 033c807418..3d588b4689 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -189,6 +189,7 @@ class Document(BaseDocument): self.validate_higher_perm_levels() self.flags.in_insert = True + self._validate_links() self.run_before_save_methods() self._validate() self.set_docstatus() @@ -260,6 +261,7 @@ class Document(BaseDocument): self.check_if_latest() self.set_parent_in_children() self.validate_higher_perm_levels() + self._validate_links() self.run_before_save_methods() if self._action != "cancel": @@ -402,7 +404,6 @@ class Document(BaseDocument): def _validate(self): self._validate_mandatory() - self._validate_links() self._validate_selects() self._validate_constants() self._validate_length() diff --git a/frappe/public/css/docs.css b/frappe/public/css/docs.css index 2fdd0ae21d..7f07e8ac91 100644 --- a/frappe/public/css/docs.css +++ b/frappe/public/css/docs.css @@ -133,6 +133,7 @@ background-color: #ff5858; } .navbar-form .awesomplete { + margin-left: -15px; width: 300px; } @media (max-width: 1199px) { @@ -195,13 +196,14 @@ } #navbar-breadcrumbs > li > a { padding: 6px 15px 10px 0px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 170px; } @media (min-width: 991px) and (max-width: 1199px) { #navbar-breadcrumbs > li > a { - max-width: 143px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + max-width: 120px; } } .toolbar-user-fullname { diff --git a/frappe/public/js/frappe/form/footer/form_footer.html b/frappe/public/js/frappe/form/footer/form_footer.html index 00ab0468ae..5319950108 100644 --- a/frappe/public/js/frappe/form/footer/form_footer.html +++ b/frappe/public/js/frappe/form/footer/form_footer.html @@ -3,6 +3,6 @@
diff --git a/frappe/public/js/frappe/misc/utils.js b/frappe/public/js/frappe/misc/utils.js index aee81ce30f..cfdbd16ee0 100644 --- a/frappe/public/js/frappe/misc/utils.js +++ b/frappe/public/js/frappe/misc/utils.js @@ -105,12 +105,12 @@ frappe.utils = { } // already there - if(y==$('body').scrollTop()) { + if(y==$('html, body').scrollTop()) { return; } if (animate!==false) { - $("body").animate({ scrollTop: y }); + $("html, body").animate({ scrollTop: y }); } else { $(window).scrollTop(y); } diff --git a/frappe/public/js/frappe/ui/filters/filters.js b/frappe/public/js/frappe/ui/filters/filters.js index 64b4cd1ed1..4927a17be1 100644 --- a/frappe/public/js/frappe/ui/filters/filters.js +++ b/frappe/public/js/frappe/ui/filters/filters.js @@ -57,6 +57,8 @@ frappe.ui.FilterList = Class.extend({ }, add_filter: function(doctype, fieldname, condition, value, hidden) { + // adds a new filter, returns true if filter has been added + // allow equal to be used as like let base_filter = this.base_list.page.fields_dict[fieldname]; if (base_filter @@ -64,7 +66,8 @@ frappe.ui.FilterList = Class.extend({ || (condition==='=' && base_filter.df.condition==='like'))) { // if filter exists in base_list, then exit this.base_list.page.fields_dict[fieldname].set_input(value); - return; + + return true; } if(doctype && fieldname @@ -75,7 +78,7 @@ frappe.ui.FilterList = Class.extend({ title: 'Invalid Filter', indicator: 'red' }); - return; + return false; } this.wrapper.find('.show_filters').toggle(true); @@ -83,7 +86,7 @@ frappe.ui.FilterList = Class.extend({ if (is_new_filter && this.wrapper.find(".is-new-filter:visible").length) { // only allow 1 new filter at a time! - return; + return false; } var filter = this.push_new_filter(doctype, fieldname, condition, value); @@ -103,7 +106,7 @@ frappe.ui.FilterList = Class.extend({ filter.$btn_group.addClass("hide"); } - return filter; + return true; }, push_new_filter: function(doctype, fieldname, condition, value) { if(this.filter_exists(doctype, fieldname, condition, value)) { @@ -128,6 +131,19 @@ frappe.ui.FilterList = Class.extend({ return filter; }, + remove: function(filter) { + // remove `filter` from flist + for (var i in this.filters) { + if (this.filters[i] === filter) { + break; + } + } + if (i!==undefined) { + // remove index + this.splice(i, 1); + } + }, + filter_exists: function(doctype, fieldname, condition, value) { var flag = false; for(var i in this.filters) { @@ -261,9 +277,11 @@ frappe.ui.Filter = Class.extend({ apply: function() { var f = this.get_value(); - this.flist.filters.pop(); + + this.flist.remove(this); this.flist.push_new_filter(f[0], f[1], f[2], f[3]); this.wrapper.remove(); + this.flist.update_filters(); }, remove: function(dont_run) { diff --git a/frappe/public/js/frappe/views/communication.js b/frappe/public/js/frappe/views/communication.js index f62914b822..1625ff4849 100755 --- a/frappe/public/js/frappe/views/communication.js +++ b/frappe/public/js/frappe/views/communication.js @@ -149,7 +149,7 @@ frappe.views.CommunicationComposer = Class.extend({ if (this.frm.subject_field && this.frm.doc[this.frm.subject_field]) { this.subject = __("Re: {0}", [this.frm.doc[this.frm.subject_field]]); } else { - this.subject = __(this.frm.doctype) + ': ' + this.frm.docname; + this.subject = __(this.frm.doctype) + ': ' + this.frm[this.frm.meta.title_field || name]; } } } diff --git a/frappe/utils/html_utils.py b/frappe/utils/html_utils.py index fa74c9ea33..3daa87d360 100644 --- a/frappe/utils/html_utils.py +++ b/frappe/utils/html_utils.py @@ -2,6 +2,17 @@ import json import bleach, bleach_whitelist.bleach_whitelist as bleach_whitelist from six import string_types +def clean_html(html): + if not isinstance(html, string_types): + return html + + return bleach.clean(html, + tags=['div', 'p', 'br', 'ul', 'ol', 'li', 'b', 'i', 'em', + 'table', 'thead', 'tbody', 'td', 'tr'], + attributes=[], + styles=['color', 'border', 'border-color'], + strip=True, strip_comments=True) + def sanitize_html(html, linkify=False): """ Sanitize HTML tags, attributes and style to prevent XSS attacks diff --git a/socketio.js b/socketio.js index 1261a22f73..13064125be 100644 --- a/socketio.js +++ b/socketio.js @@ -38,6 +38,11 @@ io.on('connection', function(socket) { } // console.log("connection!"); + if (!socket.request.headers.cookie) { + return; + } + + var sid = cookie.parse(socket.request.headers.cookie).sid if(!sid) { return;