diff options
| author | Siddarth Gajjar <sga@odoo.com> | 2018-05-30 14:52:17 +0200 |
|---|---|---|
| committer | Thibault Delavallée <tde@odoo.com> | 2018-05-30 15:39:15 +0200 |
| commit | c75c2fa9e3da007f080a4d4691d83d4c29112b1f (patch) | |
| tree | 62c1a4e36ad59afce79d77bba3eeeed9ea9f36b7 /addons/web | |
| parent | cda8bdc8b371429c7f88326a99cb5ebf6c446a1d (diff) | |
[IMP] web: add a badge based widget for selection fields
This commit introduces a new widget to be used for selection-based fields.
Valid choices are displayed using rectangular badges and not like the
standard list. This widget is valid for selection and many2one fields
like selection or radio widgets.
Co-authored-by: Siddarth Gajjar <sga@odoo.com>
Co-authored-by: Mohammed Shekha <msh@openerp.com>
Diffstat (limited to 'addons/web')
| -rw-r--r-- | addons/web/static/src/js/fields/field_registry.js | 1 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/relational_fields.js | 70 | ||||
| -rw-r--r-- | addons/web/static/src/scss/fields.scss | 18 | ||||
| -rw-r--r-- | addons/web/static/src/xml/base.xml | 7 | ||||
| -rw-r--r-- | addons/web/static/tests/fields/relational_fields_tests.js | 73 |
5 files changed, 169 insertions, 0 deletions
diff --git a/addons/web/static/src/js/fields/field_registry.js b/addons/web/static/src/js/fields/field_registry.js index cebfed606fd..8ae7362b75f 100644 --- a/addons/web/static/src/js/fields/field_registry.js +++ b/addons/web/static/src/js/fields/field_registry.js @@ -60,6 +60,7 @@ registry registry .add('selection', relational_fields.FieldSelection) .add('radio', relational_fields.FieldRadio) + .add('selection_badge', relational_fields.FieldSelectionBadge) .add('many2one', relational_fields.FieldMany2One) .add('list.many2one', relational_fields.ListFieldMany2One) .add('kanban.many2one', relational_fields.KanbanFieldMany2One) diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 62cc965cc15..c86411b6cd9 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -2301,6 +2301,75 @@ var FieldRadio = FieldSelection.extend({ }, }); + +var FieldSelectionBadge = FieldSelection.extend({ + template: null, + className: 'o_field_selection_badge', + tagName: 'span', + specialData: "_fetchSpecialMany2ones", + events: _.extend({}, AbstractField.prototype.events, { + 'click span.o_selection_badge': '_onBadgeClicked', + }), + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + * @override + */ + _renderEdit: function () { + this.currentValue = this.value; + + if (this.field.type === 'many2one') { + this.currentValue = this.value && this.value.data.id; + } + this.$el.empty(); + this.$el.html(qweb.render('FieldSelectionBadge', {'values': this.values, 'current_value': this.currentValue})); + }, + /** + * Sets the possible field values. If the field is a many2one, those values + * may change during the life cycle of the widget if the domain change (an + * onchange may change the domain). + * + * @private + * @override + */ + _setValues: function () { + // Note: We can make abstract widget for common code in radio and selection badge + if (this.field.type === 'selection') { + this.values = this.field.selection || []; + } else if (this.field.type === 'many2one') { + this.values = _.map(this.record.specialData[this.name], function (val) { + return [val.id, val.display_name]; + }); + } + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {MouseEvent} event + */ + _onBadgeClicked: function (event) { + var index = $(event.target).data('index'); + var value = this.values[index]; + if (value[0] !== this.currentValue) { + if (this.field.type === 'many2one') { + this._setValue({id: value[0], display_name: value[1]}); + } else { + this._setValue(value[0]); + } + } else { + this._setValue(false); + } + }, +}); + /** * The FieldReference is a combination of a select (for the model) and * a FieldMany2one for its value. @@ -2461,6 +2530,7 @@ return { KanbanFieldMany2ManyTags: KanbanFieldMany2ManyTags, FieldRadio: FieldRadio, + FieldSelectionBadge: FieldSelectionBadge, FieldSelection: FieldSelection, FieldStatus: FieldStatus, diff --git a/addons/web/static/src/scss/fields.scss b/addons/web/static/src/scss/fields.scss index 3de64e866ac..0fd69037b0b 100644 --- a/addons/web/static/src/scss/fields.scss +++ b/addons/web/static/src/scss/fields.scss @@ -229,6 +229,24 @@ cursor: ns-resize; } + &.o_field_selection_badge { + .o_selection_badge { + display: inline-block; + margin: 0px 0px 4px 4px; + padding: 1px 6px; + color: $o-main-color-muted; + border: 1px solid $o-color-silver-dark; + cursor: pointer; + &.active { + color: $o-brand-optional; + border-color: $o-brand-optional; + } + &:hover:not(.active) { + color: darken($o-color-silver-dark, 30%); + border-color: darken($o-color-silver-dark, 30%); + } + } + } // Radio buttons &.o_field_radio { .o_radio_input { diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 0debc65dc54..458e15dd2be 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -792,6 +792,13 @@ <label class="o_form_label" t-att-for="id"><t t-esc="value[1]"/></label> </div> </t> + +<t t-name="FieldSelectionBadge"> + <span t-foreach="values" t-as="value" t-attf-class="o_selection_badge #{value[0] == current_value ? 'active' : ''}" t-att-data-index="value_index"> + <t t-esc="value[1]"/> + </span> +</t> + <t t-name="FieldMany2One"> <t t-if="widget.mode === 'readonly'"> <a t-if="!widget.nodeOptions.no_open" class="o_form_uri" href="#"/> diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index 9e1ca77a05c..913ca896b7c 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -11382,6 +11382,79 @@ QUnit.module('relational_fields', { form.destroy(); }); + + QUnit.module('FieldSelectionBadge'); + + QUnit.test('FieldSelectionBadge widget on a many2one in a new record', function (assert) { + assert.expect(6); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form>' + + '<field name="product_id" widget="selection_badge"/>' + + '</form>', + }); + + assert.ok(form.$('span.o_selection_badge').length, "should have rendered outer div"); + assert.strictEqual(form.$('span.o_selection_badge').length, 2, "should have 2 possible choices"); + assert.ok(form.$('span.o_selection_badge:contains(xphone)').length, "one of them should be xphone"); + assert.strictEqual(form.$('span.active').length, 0, "none of the input should be checked"); + + $("span.o_selection_badge:first").click(); + + assert.strictEqual(form.$('span.active').length, 1, "one of the input should be checked"); + + form.$buttons.find('.o_form_button_save').click(); + + var newRecord = _.last(this.data.partner.records); + assert.strictEqual(newRecord.product_id, 37, "should have saved record with correct value"); + form.destroy(); + }); + + QUnit.test('FieldSelectionBadge widget on a selection in a new record', function (assert) { + assert.expect(4); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form>' + + '<field name="color" widget="selection_badge"/>' + + '</form>', + }); + + assert.ok(form.$('span.o_selection_badge').length, "should have rendered outer div"); + assert.strictEqual(form.$('span.o_selection_badge').length, 2, "should have 2 possible choices"); + assert.ok(form.$('span.o_selection_badge:contains(Red)').length, "one of them should be Red"); + + // click on 2nd option + form.$("span.o_selection_badge").eq(1).click(); + + form.$buttons.find('.o_form_button_save').click(); + + var newRecord = _.last(this.data.partner.records); + assert.strictEqual(newRecord.color, 'black', "should have saved record with correct value"); + form.destroy(); + }); + + QUnit.test('FieldSelectionBadge widget on a selection in a readonly mode', function (assert) { + assert.expect(1); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form>' + + '<field name="color" widget="selection_badge" readonly="1"/>' + + '</form>', + }); + + assert.strictEqual(form.$('span.o_readonly_modifier').length, 1, "should have 1 possible value in readonly mode"); + form.destroy(); + }); + QUnit.module('FieldMany2ManyCheckBoxes'); QUnit.test('widget many2many_checkboxes', function (assert) { |
