mirror of
https://github.com/OCA/web.git
synced 2025-02-22 13:21:25 +02:00
[ADD] web_button_invisible
This commit is contained in:
3
web_button_visibility/models/__init__.py
Normal file
3
web_button_visibility/models/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from . import base
|
||||
from . import hide_button_rule
|
||||
from . import ir_model
|
||||
107
web_button_visibility/models/base.py
Normal file
107
web_button_visibility/models/base.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# Copyright 2023 ooops404
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)
|
||||
import json
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from odoo import api, models
|
||||
from odoo.osv import expression
|
||||
from odoo.tools.safe_eval import safe_eval
|
||||
|
||||
|
||||
class Base(models.AbstractModel):
|
||||
_inherit = "base"
|
||||
|
||||
@api.model
|
||||
def fields_view_get(
|
||||
self, view_id=None, view_type=False, toolbar=False, submenu=False
|
||||
):
|
||||
arch = super().fields_view_get(
|
||||
view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu
|
||||
)
|
||||
if view_type not in ["form"]:
|
||||
return arch
|
||||
if self.env.user.has_group("base.group_user"):
|
||||
restrictions = self.env["model.button.rule"].search(
|
||||
[
|
||||
("model_name", "=", self._name),
|
||||
("group_ids", "in", self.env.user.groups_id.ids),
|
||||
("action", "=", "hide"),
|
||||
]
|
||||
)
|
||||
if restrictions:
|
||||
return self.create_hide_button_field(restrictions, arch)
|
||||
return arch
|
||||
|
||||
def create_hide_button_field(self, restrictions, arch):
|
||||
"""Create a computed field which will be used in attrs of button to hide it"""
|
||||
doc = etree.XML(arch["arch"])
|
||||
for r in restrictions:
|
||||
for node in doc.xpath("//button[@name='%s']" % r.button_name):
|
||||
field_node_str = "<field name='%s' invisible='1' />"
|
||||
field_node_mod = bytes(
|
||||
'{"invisible": true,"column_invisible": true}', "utf-8"
|
||||
)
|
||||
modifiers = json.loads(node.get("modifiers", "{}"))
|
||||
visibility_field_name = r.get_button_field_name()
|
||||
if (
|
||||
modifiers
|
||||
and modifiers.get("invisible")
|
||||
and type(modifiers["invisible"]) == list
|
||||
):
|
||||
norm_dom = expression.normalize_domain(modifiers["invisible"])
|
||||
modifiers["invisible"] = expression.OR(
|
||||
[norm_dom, [(visibility_field_name, "=", True)]]
|
||||
)
|
||||
else:
|
||||
modifiers["invisible"] = [(visibility_field_name, "=", True)]
|
||||
node.set("modifiers", json.dumps(modifiers))
|
||||
new_node = etree.fromstring(field_node_str % visibility_field_name)
|
||||
new_node.set("invisible", "1")
|
||||
new_node.set("modifiers", field_node_mod)
|
||||
node.getparent().append(new_node)
|
||||
arch["arch"] = etree.tostring(doc)
|
||||
return arch
|
||||
|
||||
def _compute_hide_button(self):
|
||||
"""Compute if button needs to be hidden"""
|
||||
restrictions = self.env["model.button.rule"].search(
|
||||
[("model_name", "=", self._name)]
|
||||
)
|
||||
for record in self:
|
||||
for r in restrictions:
|
||||
if r.button_visibility_field_id:
|
||||
field_name = r.button_visibility_field_id.name
|
||||
record[field_name] = False
|
||||
if r.condition_domain:
|
||||
filtered_rec_id = record.filtered_domain(
|
||||
safe_eval(r.condition_domain)
|
||||
)
|
||||
if filtered_rec_id and r.group_ids & self.env.user.groups_id:
|
||||
record[field_name] = True
|
||||
elif r.group_ids and r.group_ids & self.env.user.groups_id:
|
||||
record[field_name] = True
|
||||
|
||||
def default_get(self, fields_list):
|
||||
res = super(Base, self).default_get(fields_list)
|
||||
if self.env.user.has_group("base.group_user"):
|
||||
vals = self._default_get_compute_hide_button_fields()
|
||||
if vals:
|
||||
res.update(vals)
|
||||
return res
|
||||
|
||||
def _default_get_compute_hide_button_fields(self):
|
||||
"""Required to hide button at the moment of new record creation"""
|
||||
restrictions = self.env["model.button.rule"].search(
|
||||
[("model_name", "=", self._name)]
|
||||
)
|
||||
values = {}
|
||||
if not restrictions:
|
||||
return values
|
||||
for r in restrictions:
|
||||
if r.button_visibility_field_id:
|
||||
field_name = r.button_visibility_field_id.name
|
||||
values[field_name] = False
|
||||
if r.group_ids and r.group_ids & self.env.user.groups_id:
|
||||
values[field_name] = True
|
||||
return values
|
||||
73
web_button_visibility/models/hide_button_rule.py
Normal file
73
web_button_visibility/models/hide_button_rule.py
Normal file
@@ -0,0 +1,73 @@
|
||||
# Copyright 2023 ooops404
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
|
||||
from odoo import _, api, exceptions, fields, models
|
||||
from odoo.tools.safe_eval import safe_eval
|
||||
|
||||
|
||||
class ModelButtonRule(models.Model):
|
||||
_name = "model.button.rule"
|
||||
_description = "Rule to hide a button"
|
||||
|
||||
button_name = fields.Char(required=True)
|
||||
action = fields.Selection([("hide", "Hide")], default="hide", required=True)
|
||||
model_id = fields.Many2one(
|
||||
"ir.model",
|
||||
ondelete="cascade",
|
||||
index=True,
|
||||
)
|
||||
model_name = fields.Char(related="model_id.model")
|
||||
condition_domain = fields.Char()
|
||||
group_ids = fields.Many2many("res.groups", required=True)
|
||||
# generated technical fields used in form attrs:
|
||||
button_visibility_field_id = fields.Many2one("ir.model.fields", ondelete="cascade")
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
rec = super().create(vals)
|
||||
if not hasattr(self.env[rec.model_name], rec.button_name):
|
||||
raise exceptions.ValidationError(
|
||||
_("Model %s has no method %s." % (rec.model_name, rec.button_name))
|
||||
)
|
||||
rec.create_restriction_field()
|
||||
return rec
|
||||
|
||||
def create_restriction_field(self):
|
||||
"""Create computed visibility field to hide button"""
|
||||
field_name = self.get_button_field_name()
|
||||
field_id = self.env["ir.model.fields"].search(
|
||||
[("name", "=", field_name), ("state", "=", "manual")]
|
||||
)
|
||||
rec_model_id = self.model_id.id
|
||||
rec_field_name = "button_visibility_field_id"
|
||||
if not field_id:
|
||||
deps = ""
|
||||
if self.condition_domain:
|
||||
deps = ",".join(
|
||||
[
|
||||
r[0] if r[0] not in ["id"] else ""
|
||||
for r in safe_eval(self.condition_domain)
|
||||
]
|
||||
)
|
||||
field_id = self.env["ir.model.fields"].create(
|
||||
{
|
||||
"name": field_name,
|
||||
"model_id": rec_model_id,
|
||||
"state": "manual",
|
||||
"field_description": "%s %s hide button field"
|
||||
% (self.model_name, self.button_name),
|
||||
"store": False,
|
||||
"ttype": "boolean",
|
||||
"compute": "for r in self: r._compute_hide_button()",
|
||||
"depends": deps,
|
||||
}
|
||||
)
|
||||
self[rec_field_name] = field_id
|
||||
|
||||
def get_button_field_name(self):
|
||||
# e.g. x_computed_button_hide_sale_order_action_draft
|
||||
return "x_computed_button_hide_%s_%s" % (
|
||||
self.model_name.replace(".", "_"),
|
||||
self.button_name,
|
||||
)
|
||||
14
web_button_visibility/models/ir_model.py
Normal file
14
web_button_visibility/models/ir_model.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# Copyright 2023 ooops404
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class IrModel(models.Model):
|
||||
_inherit = "ir.model"
|
||||
|
||||
hide_button_rule_ids = fields.One2many(
|
||||
"model.button.rule",
|
||||
"model_id",
|
||||
)
|
||||
Reference in New Issue
Block a user