From 5ffdeb19fc6d76402638c171cdbcc900dad5ce2d Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Thu, 24 Jan 2019 14:26:27 +0530 Subject: [PATCH] feat: New filter type "Is Set", "Is Not Set" --- frappe/model/db_query.py | 14 +++++++++++++- .../js/frappe/ui/filters/edit_filter.html | 18 +++--------------- frappe/public/js/frappe/ui/filters/filter.js | 16 ++++++++++++++-- frappe/utils/data.py | 3 ++- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index ca7558c77a..116255106c 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -409,6 +409,19 @@ class DatabaseQuery(object): value = get_time(f.value).strftime("%H:%M:%S.%f") fallback = "'00:00:00'" + elif f.operator.lower() == "is": + if f.value == 'set': + f.operator = '!=' + elif f.value == 'not set': + f.operator = '=' + + value = "" + fallback = '""' + can_be_null = True + + if 'ifnull' not in column_name: + column_name = 'ifnull({}, {})'.format(column_name, fallback) + elif f.operator.lower() in ("like", "not like") or (isinstance(f.value, string_types) and (not df or df.fieldtype not in ["Float", "Int", "Currency", "Percent", "Check"])): value = "" if f.value==None else f.value @@ -417,7 +430,6 @@ class DatabaseQuery(object): if f.operator.lower() in ("like", "not like") and isinstance(value, string_types): # because "like" uses backslash (\) for escaping value = value.replace("\\", "\\\\").replace("%", "%%") - else: value = flt(f.value) fallback = 0 diff --git a/frappe/public/js/frappe/ui/filters/edit_filter.html b/frappe/public/js/frappe/ui/filters/edit_filter.html index 88f3a5b20c..50b1e1b4e6 100644 --- a/frappe/public/js/frappe/ui/filters/edit_filter.html +++ b/frappe/public/js/frappe/ui/filters/edit_filter.html @@ -3,21 +3,9 @@
diff --git a/frappe/public/js/frappe/ui/filters/filter.js b/frappe/public/js/frappe/ui/filters/filter.js index 1cbbc5fc2d..6b1be4bd0f 100644 --- a/frappe/public/js/frappe/ui/filters/filter.js +++ b/frappe/public/js/frappe/ui/filters/filter.js @@ -13,13 +13,16 @@ frappe.ui.Filter = class { ["not like", __("Not Like")], ["in", __("In")], ["not in", __("Not In")], + ["is", __("Is")], [">", ">"], ["<", "<"], [">=", ">="], ["<=", "<="], ["Between", __("Between")], ["descendants of", __("Descendants Of")], - ["ancestors of", __("Ancestors Of")] + ["not descendants of", __("Not Descendants Of")], + ["ancestors of", __("Ancestors Of")], + ["not ancestors of", __("Not Ancestors Of")] ]; this.invalid_condition_map = { Date: ['like', 'not like'], @@ -37,7 +40,9 @@ frappe.ui.Filter = class { } make() { - this.filter_edit_area = $(frappe.render_template("edit_filter", {})) + this.filter_edit_area = $(frappe.render_template("edit_filter", { + conditions: this.conditions + })) .appendTo(this.parent.find('.filter-edit-area')); } @@ -395,5 +400,12 @@ frappe.ui.filter_utils = { if(condition == "Between" && (df.fieldtype == 'Date' || df.fieldtype == 'Datetime')){ df.fieldtype = 'DateRange'; } + if (condition === 'is') { + df.fieldtype = 'Select' + df.options = [ + { label: __('Set'), value: 'set' }, + { label: __('Not Set'), value: 'not set' }, + ] + } } }; diff --git a/frappe/utils/data.py b/frappe/utils/data.py index dd3d9e3c94..3e92d3e5b9 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -835,7 +835,8 @@ def get_filter(doctype, f): f.operator = "=" valid_operators = ("=", "!=", ">", "<", ">=", "<=", "like", "not like", "in", "not in", - "between", "descendants of", "ancestors of", "not descendants of", "not ancestors of") + "between", "descendants of", "ancestors of", "not descendants of", "not ancestors of", "is") + if f.operator.lower() not in valid_operators: frappe.throw(frappe._("Operator must be one of {0}").format(", ".join(valid_operators)))