+
Add new options for many2one field
+
+
+
Description
+
This modules modifies "many2one" and "many2manytags" form widgets so as to add some new display
+control options.
+
New: support many2manytags widget !
+
New: support global option management with ir.config_parameter !
+
Options provided includes possibility to remove "Create..." and/or "Create and
+Edit..." entries from many2one drop down. You can also change default number of
+proposition appearing in the drop-down. Or prevent the dialog box poping in
+case of validation error.
+
If not specified, the module will avoid proposing any of the create options
+if the current user have no permission rights to create the related object.
+
+
+
Requirements
+
Was tested on openerp 8.0, trunk, saas-5 branch. New way to import js file. (thanks to tfossoul)
+
+
+
New options
+
create boolean (Default: depends if user have create rights)
+
+Whether to display the "Create..." entry in dropdown panel.
+
create_edit boolean (Default: depends if user have create rights)
+
+Whether to display "Create and Edit..." entry in dropdown panel
+
m2o_dialog boolean (Default: depends if user have create rights)
+
+Whether to display the many2one dialog in case of validation error.
+
limit int (Default: openerp default value is 7)
+
+Number of displayed record in drop-down panel
+
+
+
ir.config_parameter options
+
Now you can disable "Create..." and "Create and Edit..." entry for all widgets in the odoo instance.
+If you disable one option, you can enable it for particular field by setting "create: True" option directly on the field definition.
+
web_m2x_options.create boolean (Default: depends if user have create rights)
+
+Whether to display the "Create..." entry in dropdown panel for all fields in the odoo instance.
+
web_m2x_options.create_edit boolean (Default: depends if user have create rights)
+
+Whether to display "Create and Edit..." entry in dropdown panel for all fields in the odoo instance.
+
web_m2x_options.limit int (Default: openerp default value is 7)
+
+Number of displayed record in drop-down panel for all fields in the odoo instance
+
To add these parameters go to Configuration -> Technical -> Parameters -> System Parameters and add new parameters like:
+
+- web_m2x_options.create: False
+- web_m2x_options.create_edit: False
+- web_m2x_options.limit: 10
+
+
+
+
Example
+
Your XML form view definition could contain:
+
+...
+<field name="partner_id" options="{'limit': 10, 'create': false, 'create_edit': false}"/>
+...
+
+
+
+
Note
+
Double check that you have no inherited view that remote options you set on a field !
+If nothing work, add a debugger in the first ligne of get_search_result method and enable debug mode in OpenERP. When you write something in a many2one field, javascript debugger should pause. If not verify your installation.
+
+
+
+
diff --git a/web_m2x_options/static/src/js/form.js b/web_m2x_options/static/src/js/form.js
new file mode 100644
index 000000000..de54a9d83
--- /dev/null
+++ b/web_m2x_options/static/src/js/form.js
@@ -0,0 +1,476 @@
+/* Copyright 2016 0k.io,ACSONE SA/NV
+ * * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
+
+odoo.define("web_m2x_options.web_m2x_options", function (require) {
+ "use strict";
+
+ var core = require("web.core"),
+ data = require("web.data"),
+ Dialog = require("web.Dialog"),
+ view_dialogs = require("web.view_dialogs"),
+ relational_fields = require("web.relational_fields"),
+ rpc = require("web.rpc");
+
+ var _t = core._t,
+ FieldMany2ManyTags = relational_fields.FieldMany2ManyTags,
+ FieldMany2One = relational_fields.FieldMany2One,
+ FormFieldMany2ManyTags = relational_fields.FormFieldMany2ManyTags;
+
+ var web_m2x_options = rpc.query({
+ model: "ir.config_parameter",
+ method: "get_web_m2x_options",
+ });
+
+ var M2ODialog = Dialog.extend({
+ template: "M2ODialog",
+ init: function (parent, name, value) {
+ this.name = name;
+ this.value = value;
+ this._super(parent, {
+ title: _.str.sprintf(_t("Create a %s"), this.name),
+ size: "medium",
+ buttons: [
+ {
+ text: _t("Create"),
+ classes: "btn-primary",
+ click: function () {
+ if (this.$("input").val()) {
+ this.trigger_up("quick_create", {
+ value: this.$("input").val(),
+ });
+ this.close(true);
+ } else {
+ this.$("input").focus();
+ }
+ },
+ },
+ {
+ text: _t("Create and edit"),
+ classes: "btn-primary",
+ close: true,
+ click: function () {
+ this.trigger_up("search_create_popup", {
+ view_type: "form",
+ value: this.$("input").val(),
+ });
+ },
+ },
+ {
+ text: _t("Cancel"),
+ close: true,
+ },
+ ],
+ });
+ },
+ start: function () {
+ this.$("p").text(
+ _.str.sprintf(
+ _t(
+ "You are creating a new %s, are you sure it does not exist yet?"
+ ),
+ this.name
+ )
+ );
+ this.$("input").val(this.value);
+ },
+ /**
+ * @override
+ * @param {Boolean} isSet
+ */
+ close: function (isSet) {
+ this.isSet = isSet;
+ this._super.apply(this, arguments);
+ },
+ /**
+ * @override
+ */
+ destroy: function () {
+ if (!this.isSet) {
+ this.trigger_up("closed_unset");
+ }
+ this._super.apply(this, arguments);
+ },
+ });
+
+ FieldMany2One.include({
+ start: function () {
+ this._super.apply(this, arguments);
+ return this.get_options();
+ },
+
+ get_options: function () {
+ var self = this;
+ if (_.isUndefined(this.ir_options_loaded)) {
+ this.ir_options_loaded = $.Deferred();
+ this.ir_options = {};
+ web_m2x_options.then(function (records) {
+ _(records).each(function (record) {
+ self.ir_options[record.key] = record.value;
+ });
+ self.ir_options_loaded.resolve();
+ });
+ }
+ return $.when();
+ },
+
+ is_option_set: function (option) {
+ if (_.isUndefined(option)) return false;
+ if (typeof option === "string")
+ return option === "true" || option === "True";
+ if (typeof option === "boolean") return option;
+ return false;
+ },
+
+ _onInputFocusout: function () {
+ var m2o_dialog_opt =
+ this.is_option_set(this.nodeOptions.m2o_dialog) ||
+ (_.isUndefined(this.nodeOptions.m2o_dialog) &&
+ this.is_option_set(
+ this.ir_options["web_m2x_options.m2o_dialog"]
+ )) ||
+ (_.isUndefined(this.nodeOptions.m2o_dialog) &&
+ _.isUndefined(this.ir_options["web_m2x_options.m2o_dialog"]));
+ if (this.can_create && this.floating && m2o_dialog_opt) {
+ new M2ODialog(this, this.string, this.$input.val()).open();
+ }
+ },
+
+ _search: function (search_val) {
+ var self = this;
+ if (search_val === undefined) {
+ return this._super.apply(this, arguments);
+ }
+ var def = new Promise((resolve) => {
+ // Add options limit used to change number of selections record
+ // returned.
+ if (!_.isUndefined(self.ir_options["web_m2x_options.limit"])) {
+ this.limit = parseInt(self.ir_options["web_m2x_options.limit"], 10);
+ }
+
+ if (typeof self.nodeOptions.limit === "number") {
+ self.limit = self.nodeOptions.limit;
+ }
+
+ // Add options field_color and colors to color item(s) depending on field_color value
+ self.field_color = self.nodeOptions.field_color;
+ self.colors = self.nodeOptions.colors;
+
+ var context = self.record.getContext(self.recordParams);
+ var domain = self.record.getDomain(self.recordParams);
+
+ var blacklisted_ids = self._getSearchBlacklist();
+ if (blacklisted_ids.length > 0) {
+ domain.push(["id", "not in", blacklisted_ids]);
+ }
+
+ self._rpc({
+ model: self.field.relation,
+ method: "name_search",
+ kwargs: {
+ name: search_val,
+ args: domain,
+ operator: "ilike",
+ limit: self.limit + 1,
+ context: context,
+ },
+ }).then((result) => {
+ // Possible selections for the m2o
+ var values = _.map(result, (x) => {
+ x[1] = self._getDisplayName(x[1]);
+ return {
+ label:
+ _.str.escapeHTML(x[1].trim()) || data.noDisplayContent,
+ value: x[1],
+ name: x[1],
+ id: x[0],
+ };
+ });
+
+ // Search result value colors
+ if (self.colors && self.field_color) {
+ var value_ids = [];
+ for (var val_index in values) {
+ value_ids.push(values[val_index].id);
+ }
+ self._rpc({
+ model: self.field.relation,
+ method: "search_read",
+ fields: [self.field_color],
+ domain: [["id", "in", value_ids]],
+ }).then((objects) => {
+ for (var index in objects) {
+ for (var index_value in values) {
+ if (values[index_value].id === objects[index].id) {
+ // Find value in values by comparing ids
+ var value = values[index_value];
+ // Find color with field value as key
+ var color =
+ self.colors[
+ objects[index][self.field_color]
+ ] || "black";
+ value.label =
+ '