[18.0][IMP] web_form_banner: client-side fast path for simple rules#1
Open
dnplkndll wants to merge 7 commits into
Open
[18.0][IMP] web_form_banner: client-side fast path for simple rules#1dnplkndll wants to merge 7 commits into
dnplkndll wants to merge 7 commits into
Conversation
test_position_relative_to_sheet asserts the partner_name_length demo banner is immediately before <sheet>. Adding a second active demo rule on res.partner (the new client-side demo) shifts the sibling indexes by 1 and the assertion fails (3 != 4). Match the existing pattern for rule_email / rule_tag: deactivate the new rule_client_side in setUpClass so the position check stays exact. The new client-side tests don't depend on the demo rule and continue to work via _make_client_rule().
Adds a concurrency block to both fork workflows so pushing a new commit to the same ref cancels still-running workflow instances. With our iteration pattern (multiple empty commits to retrigger CI) this drops ~3× the runner load. Strip before opening upstream OCA PR — block is wrapped in '>>> FORK-LOCAL BLOCK <<<' markers so a single sed strips both files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Every banner rule today fires a server RPC (
compute_message) per trigger-field change. For typical conditions —state == 'draft' and amount_total > 1000— Odoo's view compiler already evaluates exactly that kind of expression purely client-side viapy.jsininvisible=attributes. The round-trip isn't needed for the 80% case.What
Per-rule
client_sideopt-in. When enabled:<field name="..."/>tags (Odoo-native, reactive) plus the existing${field_name}sugar that rewrites to those tags atget_viewtime.Generated arch
For a rule with
client_condition: not email and name, messageContact <strong>${name}</strong> has no email., target xpath//sheet, onres.partnerform:Toggle
emailon/off in the form → banner appears/disappears instantly. Zero Network-tab activity, zerocompute_messageRPC.Defensive auto-injection
If
client_conditionreferences a field that the form view doesn't declare, py.js raisesName 'X' is not definedat render time and crashes any browser test that opens the form. Theget_viewoverride parses the condition viaast.parse, extracts every leftmost-Name reference, filters out py.js reserved names + names not on the model + names already declared, and auto-injects the remaining as<field name="X" invisible="True"/>siblings. Any admin-defined rule referencing a non-loaded field now Just Works.What works in
client_conditionComparisons, boolean ops,
in/not in, attribute access (partner_id.email), built-ins (len,bool,min,max,set), ternaryx if cond else y.What does NOT work — keep server-side mode
Arbitrary method calls (
.filtered(),.mapped()), slicing, lambdas, comprehensions, ORM searches, per-record severity overrides,${X.Y}dotted interpolation.Files
models/web_form_banner_rule.pyclient_side+client_conditionfields,_check_client_conditionconstraint viaast.parse,_to_client_archfor${var}→<field/>models/ir_model.pyget_viewbranches onrule.client_side;_client_rule_missing_fieldsreturns hidden field shims; banner built via lxml element APIstatic/src/js/web_form_banner.esm.jsbannersIn()skipsdata-client="1"divsviews/web_form_banner_rule_views.xmltests/test_web_form_banner.py${var}sugar, HTML escaping, missing/malformed condition rejection, hidden-field auto-injection with dedup, py.js-reserved-name skipping, dotted-${}rejection, quote-bearing conditions, position=after, multi-rule field sharingdemo/web_form_banner_rule_demo.xmlnot email and name)readme/USAGE.md+ROADMAP.md+CONTRIBUTORS.md__manifest__.py18.0.1.2.0, add Ledoweb co-author +maintainers=["dnplkndll"]Notable correctness details
etree.ElementAPI rather than f-string XML — single quotes in conditions likestate == 'draft'would otherwise terminate theinvisible='...'attribute mid-expression. Caught during review; covered bytest_client_side_handles_quoted_string_literals.${var}sugar restricted to bare field names. Dotted paths like${partner_id.email}would rewrite to invalid form arch. Covered bytest_client_side_rejects_dotted_var_sugar. Documented in USAGE.Verification
Local fresh-DB
--test-enable: 20 tests, 0 failures.Fork CI on ledoent self-hosted runners (
hetzner-k3s-ledoent): all 5 jobs green (commiteffeea0on 18.0-imp-web_form_banner-client-side).Practice run scope
PR opened against the fork (not OCA upstream) to exercise the review workflow. Will close after squashing/promoting to OCA/web.
Test plan
>>> FORK-LOCAL BLOCK <<<before promoting upstream