diff --git a/server_action_mass_edit/__manifest__.py b/server_action_mass_edit/__manifest__.py index f718a29b09..bc2aaeb3e9 100644 --- a/server_action_mass_edit/__manifest__.py +++ b/server_action_mass_edit/__manifest__.py @@ -20,5 +20,11 @@ "views/ir_actions_server.xml", "wizard/mass_editing_wizard.xml", ], + "assets": { + "web.assets_backend": [ + "/server_action_mass_edit/static/src/js/record.esm.js", + "/server_action_mass_edit/static/src/js/static_list.esm.js", + ] + }, "demo": ["demo/mass_editing.xml"], } diff --git a/server_action_mass_edit/models/ir_actions_server_mass_edit_line.py b/server_action_mass_edit/models/ir_actions_server_mass_edit_line.py index a3184c1a72..7af26d6247 100644 --- a/server_action_mass_edit/models/ir_actions_server_mass_edit_line.py +++ b/server_action_mass_edit/models/ir_actions_server_mass_edit_line.py @@ -33,6 +33,7 @@ class IrActionsServerMassEditLine(models.Model): ("name", "not in", %s), ("ttype", "not in", ["reference", "function"]), ("model_id", "=", model_id), + ("readonly", "!=", True), ] """ % str(MAGIC_FIELDS), diff --git a/server_action_mass_edit/static/src/js/record.esm.js b/server_action_mass_edit/static/src/js/record.esm.js new file mode 100644 index 0000000000..ed6875ad82 --- /dev/null +++ b/server_action_mass_edit/static/src/js/record.esm.js @@ -0,0 +1,29 @@ +/** @odoo-module **/ +import {Record} from "@web/model/relational_model/record"; +import {patch} from "@web/core/utils/patch"; + +patch(Record.prototype, { + _createStaticListDatapoint(data, fieldName) { + const {related, limit, defaultOrderBy} = this.activeFields[fieldName]; + const config = { + resModel: this.fields[fieldName].relation, + activeFields: (related && related.activeFields) || {}, + fields: (related && related.fields) || {}, + relationField: this.fields[fieldName].relation_field || false, + offset: 0, + // To prevent the TypeError: data.map is not a function while set/remove/add + // value in wizard + resIds: Array.isArray(data) ? data.map((r) => r.id || null) : [], + orderBy: defaultOrderBy || [], + limit: limit || Number.MAX_SAFE_INTEGER, + currentCompanyId: this.currentCompanyId, + context: {}, + }; + const options = { + onUpdate: ({withoutOnchange} = {}) => + this._update({[fieldName]: []}, {withoutOnchange}), + parent: this, + }; + return new this.model.constructor.StaticList(this.model, config, data, options); + }, +}); diff --git a/server_action_mass_edit/static/src/js/static_list.esm.js b/server_action_mass_edit/static/src/js/static_list.esm.js new file mode 100644 index 0000000000..7853aaca04 --- /dev/null +++ b/server_action_mass_edit/static/src/js/static_list.esm.js @@ -0,0 +1,31 @@ +/** @odoo-module **/ +import {StaticList} from "@web/model/relational_model/static_list"; +import {markRaw} from "@odoo/owl"; +import {patch} from "@web/core/utils/patch"; + +patch(StaticList.prototype, { + setup(config, data, options = {}) { + this._parent = options.parent; + this._onUpdate = options.onUpdate; + + this._cache = markRaw({}); + this._commands = []; + this._savePoint = undefined; + this._unknownRecordCommands = {}; + this._currentIds = [...this.resIds]; + this._needsReordering = false; + this._tmpIncreaseLimit = 0; + this._extendedRecords = new Set(); + // To prevent the TypeError: data.slice is not a function" while set/remove/add + // value in wizard + this.records = Array.isArray(data) + ? data + .slice(this.offset, this.limit) + .map((r) => this._createRecordDatapoint(r)) + : []; + this.count = this.resIds.length; + this.handleField = Object.keys(this.activeFields).find( + (fieldName) => this.activeFields[fieldName].isHandle + ); + }, +}); diff --git a/server_action_mass_edit/wizard/mass_editing_wizard.py b/server_action_mass_edit/wizard/mass_editing_wizard.py index 32d886f145..6be1faa3d9 100644 --- a/server_action_mass_edit/wizard/mass_editing_wizard.py +++ b/server_action_mass_edit/wizard/mass_editing_wizard.py @@ -25,11 +25,11 @@ def default_get(self, fields): res = super().default_get(fields) server_action_id = self.env.context.get("server_action_id") server_action = self.env["ir.actions.server"].sudo().browse(server_action_id) + active_ids = self.env.context.get("active_ids") if not server_action: return res - active_ids = self.env.context.get("active_ids") or self.env["ir.actions.server"] original_active_ids = self.env.context.get("original_active_ids", active_ids) operation_description_info = False operation_description_warning = False @@ -121,7 +121,7 @@ def _prepare_fields(self, line, field, field_info): if field.ttype == "many2many": selection = [ ("ignore", _("Don't touch")), - ("set", _("Set")), + ("set_m2m", _("Set")), ("remove_m2m", _("Remove")), ("add", _("Add")), ] @@ -181,9 +181,9 @@ def _insert_field_in_arch(self, line, field, main_xml_group): dummy, tree_view = comodel._get_view(view_type="tree") field_context = {} if form_view: - field_context["form_view_ref"] = form_view.id + field_context["form_view_ref"] = form_view.xml_id if tree_view: - field_context["tree_view_ref"] = tree_view.id + field_context["tree_view_ref"] = tree_view.xml_id if field_context: field_element.attrib["context"] = json.dumps(field_context) else: @@ -204,9 +204,7 @@ def _insert_field_in_arch(self, line, field, main_xml_group): def _get_field_options(self, field): return { "name": field.name, - "modifiers": '{"invisible": "\ - "[["selection__%s", "in", ["ignore", "remove"]]]}' - % field.name, + "invisible": 'selection__%s in ["ignore", "remove", False]' % field.name, "class": "w-75", } @@ -284,11 +282,9 @@ def create(self, vals_list): if key.startswith("selection_"): split_key = key.split("__", 1)[1] if val == "set" or val == "add_o2m": - if val == "set": - vals[split_key] = vals[split_key][0][1:] values.update({split_key: vals.get(split_key, False)}) - elif val == "set_o2m": + elif val == "set_o2m" or val == "set_m2m": values.update( {split_key: [(6, 0, [])] + vals.get(split_key, [])} ) @@ -299,19 +295,15 @@ def create(self, vals_list): elif val == "remove_m2m": m2m_list = [] if vals.get(split_key): - vals[split_key][0] = vals[split_key][0][1:] - for m2m_id in vals.get(split_key, False)[0]: - m2m_list.append((3, m2m_id)) + for m2m_id in vals.get(split_key, False): + m2m_list.append((3, m2m_id[1])) if m2m_list: values.update({split_key: m2m_list}) else: values.update({split_key: [(5, 0, [])]}) elif val == "add": - m2m_list = [] - for m2m_id in vals.get(split_key, False): - m2m_list.append(m2m_id) - values.update({split_key: m2m_list}) + values.update({split_key: vals.get(split_key, False)}) if values: self.env[server_action.model_id.model].browse(