From cab1e766859145098c66b5c8d6a413be761851f8 Mon Sep 17 00:00:00 2001 From: hda Date: Mon, 8 Mar 2021 13:11:58 +0100 Subject: [PATCH 1/6] [MIG] web_m2x_options: mru --- web_m2x_options/models/ir_config_parameter.py | 1 + web_m2x_options/readme/USAGE.rst | 9 ++ web_m2x_options/static/src/js/form.js | 131 +++++++++++++++++- .../static/src/scss/web_m2x_options.scss | 3 + web_m2x_options/static/src/xml/base.xml | 7 + 5 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 web_m2x_options/static/src/scss/web_m2x_options.scss diff --git a/web_m2x_options/models/ir_config_parameter.py b/web_m2x_options/models/ir_config_parameter.py index 8e7228f086e8..13b7b9d35afe 100644 --- a/web_m2x_options/models/ir_config_parameter.py +++ b/web_m2x_options/models/ir_config_parameter.py @@ -12,5 +12,6 @@ def get_web_m2x_options(self): "web_m2x_options.limit", "web_m2x_options.search_more", "web_m2x_options.m2o_dialog", + "web_m2x_options.search_mru", ] return self.sudo().search_read([["key", "in", opts]], ["key", "value"]) diff --git a/web_m2x_options/readme/USAGE.rst b/web_m2x_options/readme/USAGE.rst index 1da37a22898a..c9679c4919e4 100644 --- a/web_m2x_options/readme/USAGE.rst +++ b/web_m2x_options/readme/USAGE.rst @@ -43,6 +43,10 @@ in the field's options dict Deactivates the color picker on many2many_tags buttons to do nothing (ignored if open is set) +``search_mru`` *boolean* (Default: ``False``) + + Display the MRU list stored in the localstorage before the user start typing. + ir.config_parameter options ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -69,6 +73,10 @@ If you disable one option, you can enable it for particular field by setting "cr Whether the field should always show "Search more..." entry or not. +``web_m2x_options.search_mru`` *boolean* (Default: default value is ``False``) + + Display the MRU list stored in the localstorage before the user start typing. + To add these parameters go to Configuration -> Technical -> Parameters -> System Parameters and add new parameters like: - web_m2x_options.create: False @@ -76,6 +84,7 @@ To add these parameters go to Configuration -> Technical -> Parameters -> System - web_m2x_options.m2o_dialog: False - web_m2x_options.limit: 10 - web_m2x_options.search_more: True +- web_m2x_options.search_mru: False Example diff --git a/web_m2x_options/static/src/js/form.js b/web_m2x_options/static/src/js/form.js index 2466de52dc52..7eadcdf33b87 100644 --- a/web_m2x_options/static/src/js/form.js +++ b/web_m2x_options/static/src/js/form.js @@ -135,6 +135,27 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { } }, + compute_mru_key: function() { + var self = this, + model = self.model, + db = odoo.session_info.db, + action = self.record.context.params.action + "_" + self.viewType; + return db + "/" + model + "/" + action + "/" + self.name; + }, + + get_mru_ids: function() { + var mru_option = "web_m2x_options_mru", + self = this; + var restore_mru_ids = JSON.parse(localStorage.getItem(mru_option)), + key = self.compute_mru_key(); + if (restore_mru_ids) { + if (!_.isUndefined(restore_mru_ids[key])) { + return restore_mru_ids[key]; + } + } + return []; + }, + _search: function(search_val) { var self = this; if (search_val === undefined) { @@ -163,6 +184,27 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { domain.push(["id", "not in", blacklisted_ids]); } + var can_search_mru = + self.nodeOptions && + self.is_option_set(self.nodeOptions.search_mru), + search_mru_undef = _.isUndefined(self.nodeOptions.search_mru), + search_mru = self.is_option_set( + self.ir_options["web_m2x_options.search_mru"] + ); + + var mru_ids = []; + var in_search_mru = false; + if ( + search_val == "" && + (can_search_mru || (search_mru_undef && search_mru)) + ) { + mru_ids = self.get_mru_ids(); + if (mru_ids.length > 0) { + domain.push(["id", "in", mru_ids]); + in_search_mru = true; + } + } + self._rpc({ model: self.field.relation, method: "name_search", @@ -177,14 +219,26 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { // Possible selections for the m2o var values = _.map(result, x => { x[1] = self._getDisplayName(x[1]); - return { + const val = { label: _.str.escapeHTML(x[1].trim()) || data.noDisplayContent, value: x[1], name: x[1], id: x[0], }; + if (in_search_mru) { + val.classname = "web_m2x_dropdown_option_mru"; + } + return val; }); + // If we are in a mru search, reorder the result list in the + // same order as the one stored to keep the saved preference + // order (The most recent ones first) + if (in_search_mru) { + values = _(values).sortBy(function(item) { + return mru_ids.indexOf(item.id); + }); + } // Search result value colors if (self.colors && self.field_color) { @@ -235,7 +289,7 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { self.ir_options["web_m2x_options.search_more"] ); - if (values.length > self.limit) { + if (values.length > self.limit || in_search_mru) { values = values.slice(0, self.limit); if (can_search_more || search_more_undef || search_more) { values.push({ @@ -379,11 +433,84 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { this.orderer.add(def); return def; }, + + update_mru_ids: function() { + var self = this, + mru_option = "web_m2x_options_mru"; + var key = self.compute_mru_key(); + const field_val = _.isUndefined(self.value.data) || self.value.data.id; + // Check if the localstorage has some items for the current model + if (localStorage.getItem(mru_option)) { + var restore_mru_ids = JSON.parse(localStorage.getItem(mru_option)); + if (restore_mru_ids[key]) { + var queue = restore_mru_ids[key]; + // If the element doesn't exist in the stack + if (queue.indexOf(field_val) < 0 && field_val) { + if (queue.length < 5) { + // Add the new element at the beginning + queue.unshift(field_val); + } else { + // Remove the last element + queue.pop(); + // Add the new element at the beginning + queue.unshift(field_val); + } + restore_mru_ids[key] = queue; + } else if (queue.indexOf(field_val) >= 0 && field_val) { + // If the element already exist in the stack + var index = queue.indexOf(field_val); + // Remove the element from the list + queue.splice(index, 1); + // And put it back at the beginning + queue.unshift(field_val); + } + } else if (field_val) { + // If the element is the first one + restore_mru_ids[key] = [field_val]; + } + localStorage.setItem(mru_option, JSON.stringify(restore_mru_ids)); + } else if (field_val) { + // First time to create an entry in the localstorage + const values = {}; + values[key] = [field_val]; + localStorage.setItem(mru_option, JSON.stringify(values)); + } + }, + + commitChanges: function() { + var self = this; + // If the field value has changed and has favorites option + const has_changed = + !_.isUndefined(self.lastChangeEvent) && + self.lastChangeEvent.name === "field_changed"; + if (self.isDirty || has_changed) { + var can_search_mru = + self.nodeOptions && + self.is_option_set(self.nodeOptions.search_mru), + search_mru_undef = _.isUndefined(self.nodeOptions.search_mru), + search_mru = self.is_option_set( + self.ir_options["web_m2x_options.search_mru"] + ); + + if (can_search_mru || (search_mru_undef && search_mru)) { + self.update_mru_ids(); + } + } + }, }); FieldMany2ManyTags.include({ events: _.extend({}, FieldMany2ManyTags.prototype.events, { + "click .o_delete": function(e) { + this.remove_id( + $(e.target) + .parent() + .data("id") + ); + }, "click .badge": "_onOpenBadge", + "mousedown .o_colorpicker span": "update_color", + "focusout .o_colorpicker": "close_color_picker", }), _onDeleteTag: function(event) { diff --git a/web_m2x_options/static/src/scss/web_m2x_options.scss b/web_m2x_options/static/src/scss/web_m2x_options.scss new file mode 100644 index 000000000000..e4d8a8940fd6 --- /dev/null +++ b/web_m2x_options/static/src/scss/web_m2x_options.scss @@ -0,0 +1,3 @@ +.web_m2x_dropdown_option_mru { + font-style: italic; +} diff --git a/web_m2x_options/static/src/xml/base.xml b/web_m2x_options/static/src/xml/base.xml index a4f5ae3c7dfd..4ea0c502b5b4 100644 --- a/web_m2x_options/static/src/xml/base.xml +++ b/web_m2x_options/static/src/xml/base.xml @@ -9,4 +9,11 @@ + + + + el[0] + + + From 4c192386c2519c0dfa0d82e457abde971c4f2391 Mon Sep 17 00:00:00 2001 From: hda Date: Tue, 9 Mar 2021 07:55:08 +0100 Subject: [PATCH 2/6] [MIG] web_m2x_options: mru --- web_m2x_options/static/src/js/form.js | 63 +++++++++++++++------------ 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/web_m2x_options/static/src/js/form.js b/web_m2x_options/static/src/js/form.js index 7eadcdf33b87..6c4a43940697 100644 --- a/web_m2x_options/static/src/js/form.js +++ b/web_m2x_options/static/src/js/form.js @@ -136,18 +136,29 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { }, compute_mru_key: function() { - var self = this, - model = self.model, + let model = this.model, db = odoo.session_info.db, - action = self.record.context.params.action + "_" + self.viewType; - return db + "/" + model + "/" + action + "/" + self.name; + action = + !_.isUndefined(this.record.context.params) && + this.record.context.params.action; + if (!action) { + const re_action = location.href.match(/action=(\d+)&/i); + if (re_action) { + action = re_action[1]; + } else { + console.log("compute_mru_key: can't retrieve action id"); + return ""; + } + } else { + action += "_" + this.viewType; + return db + "/" + model + "/" + action + "/" + this.name; + } }, get_mru_ids: function() { - var mru_option = "web_m2x_options_mru", - self = this; - var restore_mru_ids = JSON.parse(localStorage.getItem(mru_option)), - key = self.compute_mru_key(); + const mru_option = "web_m2x_options_mru", + restore_mru_ids = JSON.parse(localStorage.getItem(mru_option)), + key = this.compute_mru_key(); if (restore_mru_ids) { if (!_.isUndefined(restore_mru_ids[key])) { return restore_mru_ids[key]; @@ -435,10 +446,9 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { }, update_mru_ids: function() { - var self = this, - mru_option = "web_m2x_options_mru"; - var key = self.compute_mru_key(); - const field_val = _.isUndefined(self.value.data) || self.value.data.id; + var mru_option = "web_m2x_options_mru"; + var key = this.compute_mru_key(); + const field_val = _.isUndefined(this.value.data) || this.value.data.id; // Check if the localstorage has some items for the current model if (localStorage.getItem(mru_option)) { var restore_mru_ids = JSON.parse(localStorage.getItem(mru_option)); @@ -464,13 +474,13 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { // And put it back at the beginning queue.unshift(field_val); } - } else if (field_val) { - // If the element is the first one + } else if (field_val && key) { + // If the element is the first one and the key is well computed restore_mru_ids[key] = [field_val]; } localStorage.setItem(mru_option, JSON.stringify(restore_mru_ids)); - } else if (field_val) { - // First time to create an entry in the localstorage + } else if (field_val && key) { + // First time to create an entry in the localstorage if the key is well computed const values = {}; values[key] = [field_val]; localStorage.setItem(mru_option, JSON.stringify(values)); @@ -478,22 +488,21 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { }, commitChanges: function() { - var self = this; // If the field value has changed and has favorites option const has_changed = - !_.isUndefined(self.lastChangeEvent) && - self.lastChangeEvent.name === "field_changed"; - if (self.isDirty || has_changed) { - var can_search_mru = - self.nodeOptions && - self.is_option_set(self.nodeOptions.search_mru), - search_mru_undef = _.isUndefined(self.nodeOptions.search_mru), - search_mru = self.is_option_set( - self.ir_options["web_m2x_options.search_mru"] + !_.isUndefined(this.lastChangeEvent) && + this.lastChangeEvent.name === "field_changed"; + if (this.isDirty || has_changed) { + const can_search_mru = + this.nodeOptions && + this.is_option_set(this.nodeOptions.search_mru), + search_mru_undef = _.isUndefined(this.nodeOptions.search_mru), + search_mru = this.is_option_set( + this.ir_options["web_m2x_options.search_mru"] ); if (can_search_mru || (search_mru_undef && search_mru)) { - self.update_mru_ids(); + this.update_mru_ids(); } } }, From 0be55e361d2b41502c935c2ba31197cdc61d1d27 Mon Sep 17 00:00:00 2001 From: hda Date: Tue, 9 Mar 2021 08:14:37 +0100 Subject: [PATCH 3/6] [MIG] web_m2x_options: mru --- web_m2x_options/static/src/js/form.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/web_m2x_options/static/src/js/form.js b/web_m2x_options/static/src/js/form.js index 6c4a43940697..b82250c252a3 100644 --- a/web_m2x_options/static/src/js/form.js +++ b/web_m2x_options/static/src/js/form.js @@ -146,13 +146,12 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { if (re_action) { action = re_action[1]; } else { - console.log("compute_mru_key: can't retrieve action id"); + console.log("ERROR - compute_mru_key: can't retrieve action id"); return ""; } - } else { - action += "_" + this.viewType; - return db + "/" + model + "/" + action + "/" + this.name; } + action += "_" + this.viewType; + return db + "/" + model + "/" + action + "/" + this.name; }, get_mru_ids: function() { From d987d42623b1d7df8d0ed10104aa0960beb7b19a Mon Sep 17 00:00:00 2001 From: hda Date: Sun, 14 Mar 2021 12:11:00 +0100 Subject: [PATCH 4/6] [MIG] web_m2x_options: mru --- web_m2x_options/static/src/js/form.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/web_m2x_options/static/src/js/form.js b/web_m2x_options/static/src/js/form.js index b82250c252a3..0f5995a1c541 100644 --- a/web_m2x_options/static/src/js/form.js +++ b/web_m2x_options/static/src/js/form.js @@ -136,22 +136,7 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { }, compute_mru_key: function() { - let model = this.model, - db = odoo.session_info.db, - action = - !_.isUndefined(this.record.context.params) && - this.record.context.params.action; - if (!action) { - const re_action = location.href.match(/action=(\d+)&/i); - if (re_action) { - action = re_action[1]; - } else { - console.log("ERROR - compute_mru_key: can't retrieve action id"); - return ""; - } - } - action += "_" + this.viewType; - return db + "/" + model + "/" + action + "/" + this.name; + return odoo.session_info.db + "/" + this.model + "/" + this.name; }, get_mru_ids: function() { From 2afebfc3219471824a4ffd103340ee682c2f43cd Mon Sep 17 00:00:00 2001 From: Laurent-Corron Date: Tue, 30 Mar 2021 13:09:48 +0200 Subject: [PATCH 5/6] [FIX] FieldMany2ManyTags --- web_m2x_options/static/src/js/form.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/web_m2x_options/static/src/js/form.js b/web_m2x_options/static/src/js/form.js index 0f5995a1c541..684b8d1bd2a9 100644 --- a/web_m2x_options/static/src/js/form.js +++ b/web_m2x_options/static/src/js/form.js @@ -494,16 +494,7 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { FieldMany2ManyTags.include({ events: _.extend({}, FieldMany2ManyTags.prototype.events, { - "click .o_delete": function(e) { - this.remove_id( - $(e.target) - .parent() - .data("id") - ); - }, "click .badge": "_onOpenBadge", - "mousedown .o_colorpicker span": "update_color", - "focusout .o_colorpicker": "close_color_picker", }), _onDeleteTag: function(event) { From deb478af55f5247f5b8f8834a8fe11de377ccb29 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 20 Oct 2022 17:16:43 +0200 Subject: [PATCH 6/6] =?UTF-8?q?[FIX]=20web=5F=C3=A9x=5Foptions:=20In=20cas?= =?UTF-8?q?e=20of=20the=20value=20of=20the=20field=20is=20undefined=20(No?= =?UTF-8?q?=20value=20selected).=20A=20boolean=20is=20added=20in=20the=20d?= =?UTF-8?q?omain=20of=20the=20localStorage=20for=20this=20field.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web_m2x_options/static/src/js/form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_m2x_options/static/src/js/form.js b/web_m2x_options/static/src/js/form.js index 684b8d1bd2a9..de598425c0f7 100644 --- a/web_m2x_options/static/src/js/form.js +++ b/web_m2x_options/static/src/js/form.js @@ -432,7 +432,7 @@ odoo.define("web_m2x_options.web_m2x_options", function(require) { update_mru_ids: function() { var mru_option = "web_m2x_options_mru"; var key = this.compute_mru_key(); - const field_val = _.isUndefined(this.value.data) || this.value.data.id; + const field_val = _.isUndefined(this.value.data) ? false : this.value.data.id; // Check if the localstorage has some items for the current model if (localStorage.getItem(mru_option)) { var restore_mru_ids = JSON.parse(localStorage.getItem(mru_option));