diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 8bee0daffac..81ca4323871 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -1048,44 +1048,37 @@ var PriorityWidget = AbstractField.extend({ // only usable for fields of type selection className: "o_priority", events: { - 'mouseover > a': function (e) { - clearTimeout(this.hover_timer); - this.$('.o_priority_star').removeClass('fa-star-o').addClass('fa-star'); - $(e.currentTarget).nextAll().removeClass('fa-star').addClass('fa-star-o'); - }, - 'mouseout > a': function () { - clearTimeout(this.hover_timer); - - var self = this; - this.hover_timer = setTimeout(function () { - self._render(); - }, 200); - }, - 'click > a': function (e) { - e.preventDefault(); - e.stopPropagation(); - - var index = $(e.currentTarget).data('index'); - var new_value = this.field.selection[index][0]; - if(new_value === this.value) { - new_value = this.empty_value; - } - this._setValue(new_value); - }, + 'mouseover > a': '_onMouseOver', + 'mouseout > a': '_onMouseOut', + 'click > a': '_onClick', }, + readonly: true, supportedFieldTypes: ['selection'], - is_set: function () { + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Like boolean fields, this widget always has a value, since the default + * value is already a valid value. + * + * @override + */ + isSet: function () { return true; }, - render_star: function (tag, is_full, index, tip) { - return $(tag) - .attr('title', tip) - .attr('data-index', index) - .addClass('o_priority_star fa') - .toggleClass('fa-star', is_full) - .toggleClass('fa-star-o', !is_full); - }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Renders a star for each possible value, readonly or edit mode doesn't matter. + * + * @override + * @private + */ _render: function () { var self = this; var index_value = this.value ? _.findIndex(this.field.selection, function (v) { @@ -1094,9 +1087,74 @@ var PriorityWidget = AbstractField.extend({ this.$el.empty(); this.empty_value = this.field.selection[0][0]; _.each(this.field.selection.slice(1), function (choice, index) { - self.$el.append(self.render_star('', index_value >= index+1, index+1, choice[1])); + self.$el.append(self._renderStar('', index_value >= index+1, index+1, choice[1])); }); }, + + /** + * Renders a star representing a particular value for this field. + * + * @param {string} tag html tag to be passed to jquery to hold the star + * @param {boolean} isFull whether the star is a full star or not + * @param {integer} index the index of the star in the series + * @param {string} tip tooltip for this star's meaning + * @private + */ + _renderStar: function (tag, isFull, index, tip) { + return $(tag) + .attr('title', tip) + .attr('data-index', index) + .addClass('o_priority_star fa') + .toggleClass('fa-star', isFull) + .toggleClass('fa-star-o', !isFull); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * Update the value of the field based on which star the user clicked on. + * + * @param {MouseEvent} event + * @private + */ + _onClick: function (event) { + event.preventDefault(); + event.stopPropagation(); + var index = $(event.currentTarget).data('index'); + var newValue = this.field.selection[index][0]; + if(newValue === this.value) { + newValue = this.empty_value; + } + this._setValue(newValue); + }, + + /** + * Reset the star display status. + * + * @private + */ + _onMouseOut: function () { + clearTimeout(this.hoverTimer); + var self = this; + this.hoverTimer = setTimeout(function () { + self._render(); + }, 200); + }, + + /** + * Colors the stars to show the user the result when clicking on it. + * + * @param {MouseEvent} event + * @private + */ + _onMouseOver: function (event) { + clearTimeout(this.hoverTimer); + this.$('.o_priority_star').removeClass('fa-star-o').addClass('fa-star'); + $(event.currentTarget).nextAll().removeClass('fa-star').addClass('fa-star-o'); + }, + }); var AttachmentImage = AbstractField.extend({ diff --git a/addons/web/static/test/fields/basic_fields_tests.js b/addons/web/static/test/fields/basic_fields_tests.js index a94f2f505be..62d1fd6efe5 100644 --- a/addons/web/static/test/fields/basic_fields_tests.js +++ b/addons/web/static/test/fields/basic_fields_tests.js @@ -29,6 +29,8 @@ QUnit.module('basic_fields', { product_id: {string: "Product", type: "many2one", relation: 'product', searchable: true}, sequence: {type: "integer", string: "Sequence", searchable: true}, currency_id: {string: "Currency", type: "many2one", relation: "currency", searchable: true}, + selection: {string: "Selection", type: "selection", searchable:true, + selection: [['normal', 'Normal'],['blocked', 'Blocked'],['done', 'Done']]}, }, records: [{ id: 1, @@ -42,6 +44,7 @@ QUnit.module('basic_fields', { p: [], timmy: [], trululu: 4, + selection: 'blocked', }, { id: 2, display_name: "second record", @@ -1667,6 +1670,218 @@ QUnit.module('basic_fields', { }); + QUnit.module('PriorityWidget'); + + QUnit.test('priority widget when not set', function (assert) { + assert.expect(4); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 2, + }); + + assert.strictEqual(form.$('.o_form_field.o_priority:not(.o_form_field_empty)').length, 1, + "widget should be considered set, even though there is no value for this field"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star').length, 2, + "should have two stars for representing each possible value: no star, one star and two stars"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star').length, 0, + "should have no full star since there is no value"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star-o').length, 2, + "should have two empty stars since there is no value"); + + form.destroy(); + }); + + QUnit.test('priority widget in form view', function (assert) { + assert.expect(22); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + }); + + assert.strictEqual(form.$('.o_form_field.o_priority:not(.o_form_field_empty)').length, 1, + "widget should be considered set"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star').length, 2, + "should have two stars for representing each possible value: no star, one star and two stars"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star').length, 1, + "should have one full star since the value is the second value"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star-o').length, 1, + "should have one empty star since the value is the second value"); + + // hover last star + form.$('.o_form_field.o_priority a.o_priority_star.fa-star-o').last().trigger('mouseover'); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star').length, 2, + "should have two stars for representing each possible value: no star, one star and two stars"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star').length, 2, + "should temporary have two full stars since we are hovering the third value"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star-o').length, 0, + "should temporary have no empty star since we are hovering the third value"); + + // Here we should test with mouseout, but currently the effect associated with it + // occurs in a setTimeout after 200ms so it's not trivial to test it here. + + // switch to edit mode and check the result + form.$buttons.find('.o_form_button_edit').click(); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star').length, 2, + "should still have two stars"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star').length, 1, + "should still have one full star since the value is the second value"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star-o').length, 1, + "should still have one empty star since the value is the second value"); + + // save + form.$buttons.find('.o_form_button_save').click(); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star').length, 2, + "should still have two stars"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star').length, 1, + "should still have one full star since the value is the second value"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star-o').length, 1, + "should still have one empty star since the value is the second value"); + + // switch to edit mode to check that the new value was properly written + form.$buttons.find('.o_form_button_edit').click(); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star').length, 2, + "should still have two stars"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star').length, 1, + "should still have one full star since the value is the second value"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star-o').length, 1, + "should still have one empty star since the value is the second value"); + + // click on the second star in edit mode + form.$('.o_form_field.o_priority a.o_priority_star.fa-star-o').last().click(); + + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star').length, 2, + "should still have two stars"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star').length, 2, + "should now have two full stars since the value is the third value"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star-o').length, 0, + "should now have no empty star since the value is the third value"); + + // save + form.$buttons.find('.o_form_button_save').click(); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star').length, 2, + "should still have two stars"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star').length, 2, + "should now have two full stars since the value is the third value"); + assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star.fa-star-o').length, 0, + "should now have no empty star since the value is the third value"); + + form.destroy(); + }); + + QUnit.test('priority widget in editable list view', function(assert) { + assert.expect(25); + + var list = createView({ + View: ListView, + model: 'partner', + data: this.data, + arch: '', + }); + + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority:not(.o_form_field_empty)').length, 1, + "widget should be considered set"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star').length, 2, + "should have two stars for representing each possible value: no star, one star and two stars"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star.fa-star').length, 1, + "should have one full star since the value is the second value"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star.fa-star-o').length, 1, + "should have one empty star since the value is the second value"); + + // Here we should test with mouseout, but currently the effect associated with it + // occurs in a setTimeout after 200ms so it's not trivial to test it here. + + // switch to edit mode and check the result + var $cell = list.$('tbody td:not(.o_list_record_selector)').first(); + $cell.click(); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star').length, 2, + "should have two stars for representing each possible value: no star, one star and two stars"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star.fa-star').length, 1, + "should have one full star since the value is the second value"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star.fa-star-o').length, 1, + "should have one empty star since the value is the second value"); + + // save + list.$buttons.find('.o_list_button_save').click(); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star').length, 2, + "should have two stars for representing each possible value: no star, one star and two stars"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star.fa-star').length, 1, + "should have one full star since the value is the second value"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star.fa-star-o').length, 1, + "should have one empty star since the value is the second value"); + + // hover last star + list.$('.o_data_row .o_priority a.o_priority_star.fa-star-o').first().trigger('mouseenter'); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star').length, 2, + "should have two stars for representing each possible value: no star, one star and two stars"); + assert.strictEqual(list.$('.o_data_row').first().find('a.o_priority_star.fa-star').length, 2, + "should temporary have two full stars since we are hovering the third value"); + assert.strictEqual(list.$('.o_data_row').first().find('a.o_priority_star.fa-star-o').length, 0, + "should temporary have no empty star since we are hovering the third value"); + + // click on the first star in readonly mode + list.$('.o_priority a.o_priority_star.fa-star').first().click(); + + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star').length, 2, + "should still have two stars"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star.fa-star').length, 0, + "should now have no full star since the value is the first value"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star.fa-star-o').length, 2, + "should now have two empty stars since the value is the first value"); + + // re-enter edit mode to force re-rendering the widget to check if the value was correctly saved + var $cell = list.$('tbody td:not(.o_list_record_selector)').first(); + $cell.click(); + + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star').length, 2, + "should still have two stars"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star.fa-star').length, 0, + "should now only have no full star since the value is the first value"); + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority a.o_priority_star.fa-star-o').length, 2, + "should now have two empty stars since the value is the first value"); + + // Click on second star in edit mode + list.$('.o_priority a.o_priority_star.fa-star-o').last().click(); + + assert.strictEqual(list.$('.o_data_row').last().find('.o_priority a.o_priority_star').length, 2, + "should still have two stars"); + assert.strictEqual(list.$('.o_data_row').last().find('.o_priority a.o_priority_star.fa-star').length, 2, + "should now have two full stars since the value is the third value"); + assert.strictEqual(list.$('.o_data_row').last().find('.o_priority a.o_priority_star.fa-star-o').length, 0, + "should now have no empty star since the value is the third value"); + + // save + list.$buttons.find('.o_list_button_save').click(); + assert.strictEqual(list.$('.o_data_row').last().find('.o_priority a.o_priority_star').length, 2, + "should still have two stars"); + assert.strictEqual(list.$('.o_data_row').last().find('.o_priority a.o_priority_star.fa-star').length, 2, + "should now have two full stars since the value is the third value"); + assert.strictEqual(list.$('.o_data_row').last().find('.o_priority a.o_priority_star.fa-star-o').length, 0, + "should now have no empty star since the value is the third value"); + + list.destroy(); + }); + + QUnit.module('FieldDomain'); QUnit.test('basic domain field usage is ok', function (assert) {