Skip to content

Commit cdf3ef6

Browse files
yostashiroAungKoKoLin1997
authored andcommitted
[IMP] web_form_banner: Partially support in-group target XPath
- Add (partial) support for elements inside groups to be a target XPath without distorting the presentation - Remove obsolete bits
1 parent fcb166a commit cdf3ef6

File tree

7 files changed

+31
-48
lines changed

7 files changed

+31
-48
lines changed

web_form_banner/README.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,9 @@ Known issues / Roadmap
212212
Banner presentation inside `<group>`
213213
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
214214

215-
Placing a full-width inline banner inside `<group>` is currently not supported. The
216-
presentation of the banner and the child fields will be distorted.
215+
Placing a full-width inline banner inside a `<group>` is only partially supported.
216+
Depending on the target XPath (especially when targeting a `<field/>` rendered by
217+
certain widgets), the banner or surrounding fields may render distorted.
217218

218219
Limitations of `draft` eval context variable
219220
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

web_form_banner/models/ir_model.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,30 +36,28 @@ def get_view(self, view_id=None, view_type="form", **options):
3636
except Exception:
3737
return res
3838
for rule in rules:
39-
target = root.xpath(rule.target_xpath or "//sheet")
40-
if not target:
39+
targets = root.xpath(rule.target_xpath or "//sheet")
40+
if not targets:
4141
continue
42-
# Lightweight placeholder; JS will fill and toggle visibility
43-
css = "o_form_banner alert alert-%s" % (rule.severity or "danger")
42+
target = targets[0]
4443
trigger_fields = ",".join(rule.trigger_field_ids.mapped("name"))
45-
node = etree.Element(
44+
banner = etree.Element(
4645
"div",
4746
{
48-
"class": css,
49-
"role": "alert",
47+
"class": "o_form_banner alert o_invisible_modifier",
48+
"role": "status",
5049
"data-rule-id": str(rule.id),
5150
"data-model": self._name,
52-
"data-default-severity": (rule.severity or "danger"),
5351
"data-trigger-fields": trigger_fields,
54-
"style": "display:none;",
5552
},
5653
)
57-
parent = target[0].getparent()
58-
if parent is None:
59-
continue
54+
in_group = any(a.tag == "group" for a in target.iterancestors())
55+
if in_group:
56+
# To avoid the layout distortion issue when the target is inside a group
57+
banner.set("colspan", "2")
6058
if rule.position == "before":
61-
parent.insert(parent.index(target[0]), node)
59+
target.addprevious(banner)
6260
else:
63-
target[0].addnext(node)
61+
target.addnext(banner)
6462
res["arch"] = etree.tostring(root, encoding="unicode")
6563
return res

web_form_banner/readme/ROADMAP.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
Banner presentation inside `<group>`
22
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33

4-
Placing a full-width inline banner inside `<group>` is currently not supported. The
5-
presentation of the banner and the child fields will be distorted.
4+
Placing a full-width inline banner inside a `<group>` is only partially supported.
5+
Depending on the target XPath (especially when targeting a `<field/>` rendered by
6+
certain widgets), the banner or surrounding fields may render distorted.
67

78
Limitations of `draft` eval context variable
89
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

web_form_banner/static/description/index.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,9 @@ <h2><a class="toc-backref" href="#toc-entry-5">Message setting examples:</a></h2
557557
<h1><a class="toc-backref" href="#toc-entry-6">Known issues / Roadmap</a></h1>
558558
<div class="section" id="banner-presentation-inside-group">
559559
<h2><a class="toc-backref" href="#toc-entry-7">Banner presentation inside <cite>&lt;group&gt;</cite></a></h2>
560-
<p>Placing a full-width inline banner inside <cite>&lt;group&gt;</cite> is currently not supported. The
561-
presentation of the banner and the child fields will be distorted.</p>
560+
<p>Placing a full-width inline banner inside a <cite>&lt;group&gt;</cite> is only partially supported.
561+
Depending on the target XPath (especially when targeting a <cite>&lt;field/&gt;</cite> rendered by
562+
certain widgets), the banner or surrounding fields may render distorted.</p>
562563
</div>
563564
<div class="section" id="limitations-of-draft-eval-context-variable">
564565
<h2><a class="toc-backref" href="#toc-entry-8">Limitations of <cite>draft</cite> eval context variable</a></h2>

web_form_banner/static/src/js/web_form_banner.esm.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ async function refreshBanners(ctrl, extraChanges) {
8585
null
8686
);
8787
if ((ctrl.__wfbSeq || 0) !== seq) return;
88-
const v = r && r.visible;
89-
el.style.display = v ? "" : "none";
90-
if (!v) continue;
91-
el.className = "o_form_banner alert alert-" + r.severity;
88+
// Replace only the alert class
89+
el.classList.remove("alert-info", "alert-warning", "alert-danger");
90+
el.classList.add("alert-" + r.severity);
91+
el.classList.toggle("o_invisible_modifier", !(r && r.visible));
9292
setHtml(el, r.html);
9393
}
9494
}

web_form_banner/static/src/scss/web_form_banner.scss

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
padding-bottom: 6px;
66
}
77

8-
// keep only a tiny gap between banners
9-
.o_form_view .o_form_banner.alert + .o_form_banner.alert {
10-
margin-top: 4px;
11-
}
12-
138
// avoid extra gaps from paragraphs inside the banner
149
.o_form_view .o_form_banner.alert p:last-child {
1510
margin-bottom: 0;

web_form_banner/tests/test_web_form_banner.py

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
from lxml import etree
55

6-
from odoo.tests.common import SavepointCase, tagged
6+
from odoo.tests.common import TransactionCase, tagged
77

88

99
@tagged("post_install", "-at_install")
10-
class TestFieldsViewGetPartnerBanner(SavepointCase):
10+
class TestFieldsViewGetPartnerBanner(TransactionCase):
1111
@classmethod
1212
def setUpClass(cls):
1313
super().setUpClass()
@@ -25,12 +25,7 @@ def setUpClass(cls):
2525
cls.p_len22 = cls.Partner.create({"name": "Professor Charles Xavier"}) # 22
2626

2727
def _get_arch_tree(self, model, view):
28-
res = model.fields_view_get(
29-
view_id=view.id,
30-
view_type="form",
31-
toolbar=False,
32-
submenu=False,
33-
)
28+
res = model.get_view(view_id=view.id, view_type="form")
3429
return etree.fromstring(res["arch"])
3530

3631
def _find_banner_node(self, tree, rule):
@@ -63,18 +58,10 @@ def test_injected_once_with_expected_attrs(self):
6358
banner_node = self._find_banner_node(tree, self.rule_name)
6459
# Basic attributes from the server injection
6560
self.assertEqual(banner_node.get("data-model"), "res.partner")
66-
self.assertEqual(
67-
banner_node.get("data-default-severity"), self.rule_name.severity
68-
)
69-
self.assertEqual(banner_node.get("role"), "alert")
70-
self.assertEqual(banner_node.get("style"), "display:none;")
61+
self.assertEqual(banner_node.get("role"), "status")
7162
# Class list includes the expected CSS classes
7263
classes = (banner_node.get("class") or "").split()
73-
for required in (
74-
"o_form_banner",
75-
"alert",
76-
"alert-%s" % (self.rule_name.severity),
77-
):
64+
for required in ("o_form_banner", "alert", "o_invisible_modifier"):
7865
self.assertIn(required, classes)
7966
# Ensure it's not duplicated
8067
all_banners = tree.xpath("//div[contains(@class,'o_form_banner')]")
@@ -99,7 +86,7 @@ def test_position_relative_to_sheet(self):
9986
def test_not_injected_on_unrelated_model(self):
10087
Company = self.env["res.company"]
10188
view = self.env.ref("base.view_company_form")
102-
res = Company.fields_view_get(view_id=view.id, view_type="form")
89+
res = Company.get_view(view_id=view.id, view_type="form")
10390
tree = etree.fromstring(res["arch"])
10491
self.assertFalse(tree.xpath("//div[contains(@class,'o_form_banner')]"))
10592

0 commit comments

Comments
 (0)