From eaacdb097ce3f511eaee8bd7631c9d883360d56a Mon Sep 17 00:00:00 2001 From: Prateeksha Singh Date: Fri, 19 May 2017 11:08:05 +0530 Subject: [PATCH] [multiselect]Add search term, filter by date range, pagination (#3333) * add search term, filter by date range, pagination * filters on the same row, ellipsis, translate msg * Rename page_len to page_length --- frappe/desk/search.py | 12 ++-- .../js/frappe/form/multi_select_dialog.js | 65 +++++++++++++++---- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/frappe/desk/search.py b/frappe/desk/search.py index f9b767bcc7..13fc67349b 100644 --- a/frappe/desk/search.py +++ b/frappe/desk/search.py @@ -8,15 +8,15 @@ from frappe.utils import cstr, unique # this is called by the Link Field @frappe.whitelist() -def search_link(doctype, txt, query=None, filters=None, page_len=20, searchfield=None): - search_widget(doctype, txt, query, searchfield=searchfield, page_len=page_len, filters=filters) +def search_link(doctype, txt, query=None, filters=None, page_length=20, searchfield=None): + search_widget(doctype, txt, query, searchfield=searchfield, page_length=page_length, filters=filters) frappe.response['results'] = build_for_autosuggest(frappe.response["values"]) del frappe.response["values"] # this is called by the search box @frappe.whitelist() def search_widget(doctype, txt, query=None, searchfield=None, start=0, - page_len=10, filters=None, filter_fields=None, as_dict=False): + page_length=10, filters=None, filter_fields=None, as_dict=False): if isinstance(filters, basestring): import json filters = json.loads(filters) @@ -31,11 +31,11 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0, if query and query.split()[0].lower()!="select": # by method frappe.response["values"] = frappe.call(query, doctype, txt, - searchfield, start, page_len, filters, as_dict=as_dict) + searchfield, start, page_length, filters, as_dict=as_dict) elif not query and doctype in standard_queries: # from standard queries search_widget(doctype, txt, standard_queries[doctype][0], - searchfield, start, page_len, filters) + searchfield, start, page_length, filters) else: if query: frappe.throw("This query style is discontinued") @@ -95,7 +95,7 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0, values = frappe.get_list(doctype, filters=filters, fields=formatted_fields, or_filters = or_filters, limit_start = start, - limit_page_length=page_len, + limit_page_length=page_length, order_by=order_by, ignore_permissions = True if doctype == "DocType" else False, # for dynamic links as_list=not as_dict) diff --git a/frappe/public/js/frappe/form/multi_select_dialog.js b/frappe/public/js/frappe/form/multi_select_dialog.js index 7a0635b6b8..f61e1021c8 100644 --- a/frappe/public/js/frappe/form/multi_select_dialog.js +++ b/frappe/public/js/frappe/form/multi_select_dialog.js @@ -18,7 +18,18 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ make: function() { let me = this; - let fields = []; + this.page_length = 20; + + let fields = [ + { + fieldtype: "Data", + label: __("Search term"), + fieldname: "search_term" + }, + { + fieldtype: "Column Break" + } + ]; let count = 0; if(!this.date_field) { this.date_field = "transaction_date"; @@ -31,12 +42,17 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ options: me.target.fields_dict[setter].df.options, default: me.setters[setter] }); - if (count++ < Object.keys(me.setters).length - 1) { + if (count++ < Object.keys(me.setters).length) { fields.push({fieldtype: "Column Break"}); } }); fields = fields.concat([ + { + "fieldname":"date_range", + "label": __("Date Range"), + "fieldtype": "DateRange", + }, { fieldtype: "Section Break" }, { fieldtype: "HTML", fieldname: "results_area" }, { fieldtype: "Button", fieldname: "make_new", label: __("Make a new " + me.doctype) } @@ -91,6 +107,19 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ this.$parent.find('.input-with-feedback').on('change', (e) => { this.get_results(); }); + + this.$parent.find('[data-fieldname="date_range"]').on('blur', (e) => { + this.get_results(); + }); + + this.$parent.find('[data-fieldname="search_term"]').on('input', (e) => { + var $this = $(this); + clearTimeout($this.data('timeout')); + $this.data('timeout', setTimeout(function() { + me.get_results(); + }, 300)); + }); + this.$parent.on('click', '.btn[data-fieldname="make_new"]', (e) => { frappe.route_options = {}; Object.keys(this.setters).forEach(function(setter) { @@ -118,17 +147,17 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ columns.forEach(function(column) { contents += `
${ - head ? __(frappe.model.unscrub(column)) + head ? `${__(frappe.model.unscrub(column))}` - : (column !== "name" ? __(result[column]) - : ` + : (column !== "name" ? `${__(result[column])}` + : ` ${__(result[column])}`) }
`; }) let $row = $(`
-
+
${contents} @@ -139,7 +168,7 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ return $row; }, - render_result_list: function(results) { + render_result_list: function(results, more = 0) { var me = this; this.$results.empty(); if(results.length === 0) { @@ -153,6 +182,11 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ results.forEach((result) => { me.$results.append(me.make_list_row(result)); }) + if (more) { + let message = __("Only {0} entries shown. Please filter for more specific results.", [this.page_length]); + me.$results.append($(`
${message}
`)); + } }, get_results: function() { @@ -164,12 +198,17 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ me.args[setter] = filters[setter]; }); + let date_val = this.dialog.fields_dict["date_range"].get_value(); + if(date_val) { + filters[this.date_field] = ['Between', me.dialog.fields_dict["date_range"].parse(date_val)]; + } + let args = { doctype: me.doctype, - txt: '', + txt: me.dialog.fields_dict["search_term"].get_value(), filters: filters, filter_fields: Object.keys(me.setters).concat([me.date_field]), - page_len: null, + page_length: this.page_length + 1, query: this.get_query().query, as_dict: 1 } @@ -179,8 +218,12 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ no_spinner: true, args: args, callback: function(r) { - let results = []; + let results = [], more = 0; if(r.values.length) { + if(r.values.length > me.page_length){ + r.values.pop(); + more = 1; + } r.values.forEach(function(result) { if(me.date_field in result) { result["Date"] = result[me.date_field] @@ -200,7 +243,7 @@ frappe.ui.form.MultiSelectDialog = Class.extend({ // Preselect oldest entry results[0].checked = 1 } - me.render_result_list(results); + me.render_result_list(results, more); } }); },