From f41bd82f66eb25df3c80b4a283a9a5b4d7058972 Mon Sep 17 00:00:00 2001 From: Ankit Sathvara Date: Fri, 7 Jul 2017 11:45:47 +0200 Subject: [PATCH] [ADD] web: Add new widget to toogle a boolean with a slider Purpose ======= Currently, it's not possible to activate a boolean on a non-editable list view without adding 2 buttons linked to a python method. These buttons aren't aligned and the result is not pretty. This commit adds a new widget that allows to toggle a boolean record by record by clicking on the slider. --- .../web/static/src/js/fields/basic_fields.js | 47 +++++++++++++++++++ .../static/src/js/fields/field_registry.js | 2 +- addons/web/static/src/less/webclient.less | 42 +++++++++++++++++ .../static/tests/fields/basic_fields_tests.js | 18 +++++++ 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 1868a29a237..6eb828a9c7e 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -1506,6 +1506,52 @@ var FieldBooleanButton = AbstractField.extend({ }, }); +var BooleanToggle = FieldBoolean.extend({ + events: { + 'click': '_onClick' + }, + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + * @private + */ + _render: function () { + this._super.apply(this, arguments); + this._renderToggleSwitch(); + }, + + /** + * Display toggle switch + * + * @private + */ + _renderToggleSwitch: function () { + this.$el.addClass("o_boolean_toggle"); + var $div = $('
'); + $div.insertAfter(this.$("input[type=checkbox]")); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * Toggle active value + * + * @private + * @param {MouseEvent} event + */ + _onClick: function (event) { + event.stopPropagation(); + this._setValue(!this.value); + this.$el.closest(".o_data_row").toggleClass('text-muted', this.value); + }, + +}); + var StatInfo = AbstractField.extend({ supportedFieldTypes: ['integer', 'float'], @@ -2258,6 +2304,7 @@ return { FieldBinaryImage: FieldBinaryImage, FieldBoolean: FieldBoolean, FieldBooleanButton: FieldBooleanButton, + BooleanToggle: BooleanToggle, FieldChar: FieldChar, FieldDate: FieldDate, FieldDateTime: FieldDateTime, diff --git a/addons/web/static/src/js/fields/field_registry.js b/addons/web/static/src/js/fields/field_registry.js index efafec6ba6a..91bba587117 100644 --- a/addons/web/static/src/js/fields/field_registry.js +++ b/addons/web/static/src/js/fields/field_registry.js @@ -41,6 +41,7 @@ registry .add('state_selection', basic_fields.StateSelectionWidget) .add('kanban_state_selection', basic_fields.StateSelectionWidget) .add('boolean_button', basic_fields.FieldBooleanButton) + .add('boolean_toggle', basic_fields.BooleanToggle) .add('statinfo', basic_fields.StatInfo) .add('percentpie', basic_fields.FieldPercentPie) .add('float_time', basic_fields.FieldFloatTime) @@ -70,5 +71,4 @@ registry // Special fields registry .add('timezone_mismatch', special_fields.FieldTimezoneMismatch); - }); diff --git a/addons/web/static/src/less/webclient.less b/addons/web/static/src/less/webclient.less index 5e84d74b599..c63bd139872 100644 --- a/addons/web/static/src/less/webclient.less +++ b/addons/web/static/src/less/webclient.less @@ -88,3 +88,45 @@ a { .oe_highlight { .btn-primary; } + +// Boolean Toggle widget +div.o_boolean_toggle { + position: relative; + display: inline-block; + width: 32px !important; + height: 18px; + + > input { + display: none; + } + + .slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #a0a0a0; + border-radius: 24px; + + &:before { + position: absolute; + content: ""; + height: 12px; + width: 12px; + left: 3px; + bottom: 3px; + background-color: white; + border-radius: 50%; + } + } + + > input:checked + .slider { + background-color: @odoo-brand-optional; + + &:before { + .translate(14px; 0px); + } + } +} diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index c732fe35ce6..173f49080ea 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -353,6 +353,24 @@ QUnit.module('basic_fields', { form.destroy(); }); + QUnit.module('FieldBooleanToggle'); + + QUnit.test('use boolean toggle widget in form view', function (assert) { + assert.expect(2); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
', + res_id: 2, + }); + + assert.strictEqual(form.$(".o_checkbox.o_boolean_toggle").length, 1, "Boolean toggle widget applied to boolean field"); + assert.strictEqual(form.$(".o_checkbox.o_boolean_toggle").find(".slider").length, 1, "Boolean toggle contains slider to toggle"); + form.destroy(); + }); + QUnit.module('FieldToggleButton'); QUnit.test('use toggle_button in list view', function (assert) {