diff options
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/account/views/account_move_views.xml | 4 | ||||
| -rw-r--r-- | addons/account/views/account_view.xml | 4 | ||||
| -rw-r--r-- | addons/hr/views/res_users.xml | 2 | ||||
| -rw-r--r-- | addons/hr_attendance/views/hr_employee_view.xml | 2 | ||||
| -rw-r--r-- | addons/mail/wizard/mail_compose_message_view.xml | 2 | ||||
| -rw-r--r-- | addons/stock/views/product_views.xml | 2 | ||||
| -rw-r--r-- | addons/web/static/src/js/core/domain.js | 7 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_model.js | 36 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_renderer.js | 13 | ||||
| -rw-r--r-- | addons/web/static/tests/core/domain_tests.js | 21 |
10 files changed, 63 insertions, 30 deletions
diff --git a/addons/account/views/account_move_views.xml b/addons/account/views/account_move_views.xml index 7d5116f93fc..47321ee5ad0 100644 --- a/addons/account/views/account_move_views.xml +++ b/addons/account/views/account_move_views.xml @@ -634,7 +634,7 @@ placeholder="Terms" attrs="{'invisible': [('type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt'))]}"/> <span class="o_form_label mx-3 oe_edit_only" - attrs="{'invisible': [ '|', '|', '|', ('state', '!=', 'draft'), ('invoice_payment_term_id', '!=', False), ('type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt'))]}"> or </span> + attrs="{'invisible': [ '|', '|', ('state', '!=', 'draft'), ('invoice_payment_term_id', '!=', False), ('type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt'))]}"> or </span> <field name="invoice_date_due" force_save="1" placeholder="Date" attrs="{'invisible': ['|', ('invoice_payment_term_id', '!=', False), ('type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt'))]}"/> @@ -1024,7 +1024,7 @@ </sheet> <!-- Attachment preview --> <div class="o_attachment_preview" - attrs="{'invisible': ['|', '|', + attrs="{'invisible': ['|', ('type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund')), ('state', '!=', 'draft')]}" /> <!-- Chatter --> diff --git a/addons/account/views/account_view.xml b/addons/account/views/account_view.xml index 77592e57e53..78e01b03510 100644 --- a/addons/account/views/account_view.xml +++ b/addons/account/views/account_view.xml @@ -612,12 +612,12 @@ action = model.setting_init_bank_account_action() <label for="balance_start"/> <div> <field class="oe_inline" name="balance_start"/> - <button name="open_cashbox_id" attrs="{'invisible': ['|','|',('state','!=','open'),('journal_type','!=','cash')]}" string="→ Count" type="object" class="oe_edit_only oe_link oe_inline" context="{'balance':'start'}"/> + <button name="open_cashbox_id" attrs="{'invisible': ['|',('state','!=','open'),('journal_type','!=','cash')]}" string="→ Count" type="object" class="oe_edit_only oe_link oe_inline" context="{'balance':'start'}"/> </div> <label for="balance_end_real"/> <div> <field class="oe_inline" name="balance_end_real"/> - <button name="open_cashbox_id" attrs="{'invisible': ['|','|',('state','!=','open'),('journal_type','!=','cash')]}" string="→ Count" type="object" class="oe_edit_only oe_link oe_inline" context="{'balance':'close'}"/> + <button name="open_cashbox_id" attrs="{'invisible': ['|',('state','!=','open'),('journal_type','!=','cash')]}" string="→ Count" type="object" class="oe_edit_only oe_link oe_inline" context="{'balance':'close'}"/> </div> </group> </group> diff --git a/addons/hr/views/res_users.xml b/addons/hr/views/res_users.xml index 17c7f58cd1e..2caff4a2b82 100644 --- a/addons/hr/views/res_users.xml +++ b/addons/hr/views/res_users.xml @@ -55,7 +55,7 @@ class="oe_stat_button" disabled="1" invisible="context.get('from_my_profile', False)" - attrs="{'invisible': ['|', ('hr_presence_state', '=', 'absent')]}"> + attrs="{'invisible': [('hr_presence_state', '=', 'absent')]}"> <div role="img" class="fa fa-fw fa-circle text-success o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'present')]}" aria-label="Available" title="Available"/> <div role="img" class="fa fa-fw fa-circle text-warning o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'to_define')]}" aria-label="Away" title="Away"/> <div role="img" class="fa fa-fw fa-circle text-danger o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'absent')]}" aria-label="Not available" title="Not available"/> diff --git a/addons/hr_attendance/views/hr_employee_view.xml b/addons/hr_attendance/views/hr_employee_view.xml index 665a8ed0a98..abfc22d1493 100644 --- a/addons/hr_attendance/views/hr_employee_view.xml +++ b/addons/hr_attendance/views/hr_employee_view.xml @@ -63,7 +63,7 @@ <field name="arch" type="xml"> <xpath expr="//button[@id='hr_presence_button']" position="attributes"> <attribute name="attrs"> - {'invisible': ['|', '|', ('hr_presence_state', '=', 'absent'), ('attendance_state', '=', 'checked_in')]} + {'invisible': ['|', ('hr_presence_state', '=', 'absent'), ('attendance_state', '=', 'checked_in')]} </attribute> </xpath> <xpath expr="//div[@name='button_box']" position="inside"> diff --git a/addons/mail/wizard/mail_compose_message_view.xml b/addons/mail/wizard/mail_compose_message_view.xml index cee9c5a7d58..1e9b0a693ff 100644 --- a/addons/mail/wizard/mail_compose_message_view.xml +++ b/addons/mail/wizard/mail_compose_message_view.xml @@ -60,7 +60,7 @@ <field name="subject" placeholder="Subject..." required="True"/> <!-- mass post --> <field name="notify" - attrs="{'invisible':['|', ('composition_mode', '!=', 'mass_post')]}"/> + attrs="{'invisible':[('composition_mode', '!=', 'mass_post')]}"/> <!-- mass mailing --> <field name="no_auto_thread" attrs="{'invisible':[('composition_mode', '!=', 'mass_mail')]}"/> <field name="reply_to" placeholder="Email address to redirect replies..." diff --git a/addons/stock/views/product_views.xml b/addons/stock/views/product_views.xml index e0053104529..bd79c551702 100644 --- a/addons/stock/views/product_views.xml +++ b/addons/stock/views/product_views.xml @@ -373,7 +373,7 @@ <!-- change attrs of fields added in view_template_property_form to restrict the display for templates --> <xpath expr="//group[@name='group_lots_and_weight']" position="attributes"> - <attribute name="attrs">{'invisible':['|', ('type', 'not in', ['product', 'consu'])]}</attribute> + <attribute name="attrs">{'invisible': [('type', 'not in', ['product', 'consu'])]}</attribute> </xpath> <xpath expr="//group[@name='group_lots_and_weight']" position="inside"> diff --git a/addons/web/static/src/js/core/domain.js b/addons/web/static/src/js/core/domain.js index b54dd54d0b6..0db9847645d 100644 --- a/addons/web/static/src/js/core/domain.js +++ b/addons/web/static/src/js/core/domain.js @@ -383,8 +383,10 @@ var Domain = collections.Tree.extend({ * to normalize (! will be normalized in-place) * @returns {Array} the normalized JS prefix-array representation of the * given domain + * @throws {Error} if the domain is invalid and can't be normalised */ normalizeArray: function (domain) { + if (domain.length === 0) { return domain; } var expected = 1; _.each(domain, function (item) { if (item === "&" || item === "|") { @@ -395,6 +397,11 @@ var Domain = collections.Tree.extend({ }); if (expected < 0) { domain.unshift.apply(domain, _.times(Math.abs(expected), _.constant("&"))); + } else if (expected > 0) { + throw new Error(_.str.sprintf( + "invalid domain %s (missing %d segment(s))", + JSON.stringify(domain), expected + )); } return domain; }, diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 1ed8c36bb98..532af65744c 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -2259,31 +2259,27 @@ var BasicModel = AbstractModel.extend({ * context. * @param {Object} modifiers * @returns {Object} + * @throws {Error} if one of the modifier domains is invalid */ _evalModifiers: function (element, modifiers) { - var result = {}; - var self = this; - var evalContext; - function evalModifier(mod) { + let evalContext = null; + const evaluated = {}; + for (const k of ['invisible', 'column_invisible', 'readonly', 'required']) { + const mod = modifiers[k]; if (mod === undefined || mod === false || mod === true) { - return !!mod; + if (k in modifiers) { + evaluated[k] = !!mod; + } + continue; + } + try { + evalContext = evalContext || this._getEvalContext(element); + evaluated[k] = new Domain(mod, evalContext).compute(evalContext); + } catch (e) { + throw new Error(_.str.sprintf('for modifier "%s": %s', k, e.message)); } - evalContext = evalContext || self._getEvalContext(element); - return new Domain(mod, evalContext).compute(evalContext); - } - if ('invisible' in modifiers) { - result.invisible = evalModifier(modifiers.invisible); - } - if ('column_invisible' in modifiers) { - result.column_invisible = evalModifier(modifiers.column_invisible); - } - if ('readonly' in modifiers) { - result.readonly = evalModifier(modifiers.readonly); - } - if ('required' in modifiers) { - result.required = evalModifier(modifiers.required); } - return result; + return evaluated; }, /** * Fetch all name_gets for the many2ones in a group diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js index 046d10a741f..ba407b766c1 100644 --- a/addons/web/static/src/js/views/basic/basic_renderer.js +++ b/addons/web/static/src/js/views/basic/basic_renderer.js @@ -547,6 +547,7 @@ var BasicRenderer = AbstractRenderer.extend(WidgetAdapterMixin, { * value (if not given, it is set to this.mode, the mode of the renderer) * @returns {Object} for code efficiency, returns the last evaluated * modifiers for the given node and record. + * @throws {Error} if one of the modifier domains is not valid */ _registerModifiers: function (node, record, element, options) { options = options || {}; @@ -575,7 +576,15 @@ var BasicRenderer = AbstractRenderer.extend(WidgetAdapterMixin, { // Evaluate if necessary if (!modifiersData.evaluatedModifiers[record.id]) { - modifiersData.evaluatedModifiers[record.id] = record.evalModifiers(modifiersData.modifiers); + try { + modifiersData.evaluatedModifiers[record.id] = record.evalModifiers(modifiersData.modifiers); + } catch (e) { + throw new Error(_.str.sprintf( + "While parsing modifiers for %s%s: %s", + node.tag, node.tag === 'field' ? ' ' + node.attrs.name : '', + e.message + )); + } } // Element might not be given yet (a second call to the function can @@ -597,7 +606,7 @@ var BasicRenderer = AbstractRenderer.extend(WidgetAdapterMixin, { } modifiersData.elementsByRecord[record.id].push(newElement); - this._applyModifiers(modifiersData, record, newElement, options); + this._applyModifiers(modifiersData, record, newElement); } return modifiersData.evaluatedModifiers[record.id]; diff --git a/addons/web/static/tests/core/domain_tests.js b/addons/web/static/tests/core/domain_tests.js index a9c7ac48ece..e9ee5f80cf6 100644 --- a/addons/web/static/tests/core/domain_tests.js +++ b/addons/web/static/tests/core/domain_tests.js @@ -7,6 +7,11 @@ QUnit.module('core', {}, function () { QUnit.module('domain'); + QUnit.test("empty", function (assert) { + assert.expect(1); + assert.ok(new Domain([]).compute({})); + }); + QUnit.test("basic", function (assert) { assert.expect(3); @@ -59,6 +64,22 @@ QUnit.module('core', {}, function () { assert.notOk(new Domain(0).compute({})); }); + QUnit.test("invalid domains should not succeed", function (assert) { + assert.expect(3); + assert.throws( + () => new Domain(['|', ['hr_presence_state', '=', 'absent']]), + /invalid domain .* \(missing 1 segment/ + ); + assert.throws( + () => new Domain(['|', '|', ['hr_presence_state', '=', 'absent'], ['attendance_state', '=', 'checked_in']]), + /invalid domain .* \(missing 1 segment/ + ); + assert.throws( + () => new Domain(['&', ['composition_mode', '!=', 'mass_post']]), + /invalid domain .* \(missing 1 segment/ + ); + }); + QUnit.test("domain <=> condition", function (assert) { assert.expect(3); |
