diff options
| author | qsm-odoo <qsm@odoo.com> | 2017-04-19 18:06:12 +0200 |
|---|---|---|
| committer | qsm-odoo <qsm@odoo.com> | 2017-05-04 12:07:30 +0200 |
| commit | 250e716c3a12e88acb4a199b427dc47d4ec55d5d (patch) | |
| tree | 0be849fd0af8d54f556af5f1274e641200ec82ef /addons/web/static | |
| parent | 8943aae665ea906aa03bc30cada884c571738b7c (diff) | |
[REF] web, *: restore views design
Since the new views merge, a lot of design elements were broken. This
was particularly impacting the fields in the editable list view; indeed
the editable list view is not using an inline form view anymore so the
fields in the list were not properly styled as the LESS was still
defined assuming the form view environment (for example the invalid
fields were red for o2m fields in form view but not in editable list
view even though they got the right CSS class).
This commit refactor the LESS following these rules:
- No more division of non-layout and layout rules. Dividing LESS rules
in x_layout.less and x.less was a mistake. Many rules can be
considered to be layout and not layout at the same time, developers
always have to switch from one file part to the other, many CSS
selectors (and rules!) are duplicated for nothing, ...
- Field style is extracted from x_view.less and put in the new
fields.less file. As before, the fields_extra.less will contain the
rules specific to community so that the enterprise repo can override
those by replacing the whole file.
- Many classes have been renamed so that o_form_x_y becomes o_x_y as
many classes can now be applied outside of form view. These classes
should not be used in templates anyway.
The commit also changes the DOM of fields so that it is more minimalist
(no useless parent div, etc).
Input elements are not automatically styled anymore, they have to get
the o_input class explicitely. This allows to fix lots of small style
bugs of previous versions (required monetary field had not the proper
style, readonly m2m tags appeared as editable, ...). This also improves
the LESS code.
The editable list view should also completely stop flickering on chrome
and firefox.
The commit also removes the orange outline on list view dirty cells.
The commit also removes deprecated static xml, LESS and other code.
Notice there are still styles to restore/fix and LESS to improve.
Diffstat (limited to 'addons/web/static')
39 files changed, 1814 insertions, 2289 deletions
diff --git a/addons/web/static/src/js/core/dom.js b/addons/web/static/src/js/core/dom.js index 4333061f924..2dad9eb912f 100644 --- a/addons/web/static/src/js/core/dom.js +++ b/addons/web/static/src/js/core/dom.js @@ -56,7 +56,12 @@ return { if ($textarea.data("auto_resize")) { return; } - function resize () { + + var $fixedTextarea; + var minHeight; + + function resize() { + $fixedTextarea.insertAfter($textarea); var heightOffset; var style = window.getComputedStyle($textarea[0], null); if (style.boxSizing === 'content-box') { @@ -64,28 +69,25 @@ return { } else { heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth); } - $fixed_text_area.width($textarea.width()); - $fixed_text_area.val($textarea.val()); - var height = $fixed_text_area[0].scrollHeight; - $textarea.css({height: Math.max(height + heightOffset, min_height)}); + $fixedTextarea.width($textarea.width()); + $fixedTextarea.val($textarea.val()); + var height = $fixedTextarea[0].scrollHeight; + $textarea.css({height: Math.max(height + heightOffset, minHeight)}); } options = options || {}; + minHeight = (options && options.min_height) || 50; - var $fixed_text_area; - var min_height = (options && options.min_height) || 50; - if (!$fixed_text_area) { - $fixed_text_area = $('<textarea disabled>').css({ - position: 'absolute', - opacity: 0, - height: 10, - top: -10000, - left: -10000, - }); - $fixed_text_area.addClass($textarea[0].className); - $fixed_text_area.insertAfter($textarea); - $fixed_text_area.data("auto_resize", true); - } + $fixedTextarea = $('<textarea disabled>', { + class: $textarea[0].className, + }).css({ + position: 'absolute', + opacity: 0, + height: 10, + top: -10000, + left: -10000, + }); + $fixedTextarea.data("auto_resize", true); var style = window.getComputedStyle($textarea[0], null); if (style.resize === 'vertical') { @@ -101,7 +103,6 @@ return { core.bus.on('DOM_updated', options.parent, resize); core.bus.on('view_shown', options.parent, resize); } - }, /** * Detaches widgets from the DOM and performs their on_detach_callback() diff --git a/addons/web/static/src/js/fields/abstract_field.js b/addons/web/static/src/js/fields/abstract_field.js index 4948a3e3c31..dd2caaa5dd1 100644 --- a/addons/web/static/src/js/fields/abstract_field.js +++ b/addons/web/static/src/js/fields/abstract_field.js @@ -34,7 +34,6 @@ var field_utils = require('web.field_utils'); var Widget = require('web.Widget'); var AbstractField = Widget.extend({ - className: 'o_field_widget', events: { 'keydown': '_onKeydown', }, @@ -151,6 +150,7 @@ var AbstractField = Widget.extend({ var self = this; return this._super.apply(this, arguments).then(function () { self.$el.attr('name', self.name); + self.$el.addClass('o_field_widget'); return self._render(); }); }, diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index e600954b967..7b48574fb44 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -184,7 +184,7 @@ var InputField = DebouncedField.extend({ */ _prepareInput: function ($input) { this.$input = $input || $("<input/>"); - this.$input.addClass('o_form_input'); + this.$input.addClass('o_input'); this.$input.attr({ type: 'text', placeholder: this.attrs.placeholder || "", @@ -261,12 +261,13 @@ var InputField = DebouncedField.extend({ }); var FieldChar = InputField.extend({ - supportedFieldTypes: ['char'], + className: 'o_field_char', tagName: 'span', + supportedFieldTypes: ['char'], }); var FieldDate = InputField.extend({ - className: "o_form_field_date", + className: "o_field_date", tagName: "span", supportedFieldTypes: ['date'], @@ -411,7 +412,8 @@ var FieldDateTime = FieldDate.extend({ }); var FieldMonetary = InputField.extend({ - className: 'o_form_field_monetary o_list_number', + className: 'o_field_monetary o_field_number', + tagName: 'span', supportedFieldTypes: ['float', 'monetary'], resetOnAnyFieldChange: true, // Have to listen to currency changes @@ -436,6 +438,7 @@ var FieldMonetary = InputField.extend({ if (this.mode === 'edit' && this.currency) { this.tagName = 'div'; + this.className += ' o_input'; } }, @@ -554,28 +557,18 @@ var FieldBoolean = AbstractField.extend({ /** * The actual checkbox is designed in css to have full control over its * appearance, as opposed to letting the browser and the os decide how - * a checkbox should look. The actual input is disabled and hidden. + * a checkbox should look. The actual input is disabled and hidden. In + * readonly mode, the checkbox is disabled. * * @override * @private */ - _renderReadonly: function () { + _render: function () { var $checkbox = this._formatValue(this.value); this.$input = $checkbox.find('input'); - this.$el.empty().append($checkbox); - }, - - /** - * The actual checkbox is designed in css to have full control over its - * appearance, as opposed to letting the browser and the os decide how - * a checkbox should look. The actual input is hidden. - * - * @override - * @private - */ - _renderEdit: function () { - this._renderReadonly(); - this.$input.prop('disabled', false); + this.$input.prop('disabled', this.mode === 'readonly'); + this.$el.addClass($checkbox.attr('class')); + this.$el.empty().append($checkbox.contents()); }, //-------------------------------------------------------------------------- @@ -591,7 +584,6 @@ var FieldBoolean = AbstractField.extend({ _onChange: function () { this._setValue(this.$input[0].checked); }, - /** * Implement keyboard movements. Mostly useful for its environment, such * as a list view. @@ -624,6 +616,8 @@ var FieldBoolean = AbstractField.extend({ }); var FieldInteger = InputField.extend({ + className: 'o_field_integer o_field_number', + tagName: 'span', supportedFieldTypes: ['integer'], //-------------------------------------------------------------------------- @@ -669,6 +663,8 @@ var FieldInteger = InputField.extend({ }); var FieldFloat = InputField.extend({ + className: 'o_field_float o_field_number', + tagName: 'span', supportedFieldTypes: ['float'], /** @@ -696,22 +692,6 @@ var FieldFloat = InputField.extend({ isSet: function () { return this.value === 0 || this._super.apply(this, arguments); }, - - //-------------------------------------------------------------------------- - // Private - //-------------------------------------------------------------------------- - - /** - * Format value according to precision parameter. - * - * @override - * @private - */ - _renderReadonly: function () { - var value = this._formatValue(this.value); - var $span = $('<span>').addClass('o_form_field o_form_field_number').text(value); - this.$el.html($span); - }, }); var FieldFloatTime = FieldFloat.extend({ @@ -743,21 +723,28 @@ var FieldFloatTime = FieldFloat.extend({ }); var FieldText = DebouncedField.extend({ + className: 'o_field_text', supportedFieldTypes: ['text'], /** - * In edit mode, the text widget contains a textarea. We append it in - * start() instead of _renderEdit() to keep the same textarea even - * if several _renderEdit are done. This allows to keep the cursor - * position and to autoresize only once. + * @constructor + */ + init: function () { + this._super.apply(this, arguments); + + if (this.mode === 'edit') { + this.tagName = 'textarea'; + this.className += ' o_input'; + } + }, + /** + * As it it done in the start function, the autoresize is done only once. * * @override */ start: function () { - this.$el.addClass('o_list_text o_form_textarea'); - if (this.mode === 'edit') { - this.$textarea = $('<textarea>').appendTo(this.$el); + this.$textarea = this.$el; if (this.attrs.placeholder) { this.$textarea.attr('placeholder', this.attrs.placeholder); } @@ -816,13 +803,14 @@ var FieldText = DebouncedField.extend({ * Displays a handle to modify the sequence. */ var HandleWidget = AbstractField.extend({ - tagName: 'span', className: 'o_row_handle fa fa-arrows ui-sortable-handle', + tagName: 'span', description: "", supportedFieldTypes: ['integer'], }); -var EmailWidget = InputField.extend({ +var FieldEmail = InputField.extend({ + className: 'o_field_email', prefix: 'mailto', supportedFieldTypes: ['char'], @@ -853,7 +841,8 @@ var EmailWidget = InputField.extend({ } }); -var FieldPhone = EmailWidget.extend({ +var FieldPhone = FieldEmail.extend({ + className: 'o_field_phone', prefix: 'tel', /** @@ -907,6 +896,7 @@ var FieldPhone = EmailWidget.extend({ }); var UrlWidget = InputField.extend({ + className: 'o_field_url', supportedFieldTypes: ['char'], /** @@ -939,9 +929,9 @@ var UrlWidget = InputField.extend({ var AbstractFieldBinary = AbstractField.extend({ events: _.extend({}, AbstractField.prototype.events, { - 'change .o_form_input_file': 'on_file_change', + 'change .o_input_file': 'on_file_change', 'click .o_select_file_button': function () { - this.$('.o_form_input_file').click(); + this.$('.o_input_file').click(); }, 'click .o_clear_file_button': 'on_clear', }), @@ -1084,8 +1074,8 @@ var FieldBinaryFile = AbstractFieldBinary.extend({ this.on_save_as(event); } }, - 'click .o_form_input': function () { // eq[0] - this.$('.o_form_input_file').click(); + 'click .o_input': function () { // eq[0] + this.$('.o_input_file').click(); }, }), supportedFieldTypes: ['binary'], @@ -1106,7 +1096,7 @@ var FieldBinaryFile = AbstractFieldBinary.extend({ if (this.value) { this.$el.children().removeClass('o_hidden'); this.$('.o_select_file_button').first().addClass('o_hidden'); - this.$('.o_form_input').eq(0).val(this.filename_value || this.value); + this.$('.o_input').eq(0).val(this.filename_value || this.value); } else { this.$el.children().addClass('o_hidden'); this.$('.o_select_file_button').first().removeClass('o_hidden'); @@ -1727,8 +1717,8 @@ var FieldToggleBoolean = AbstractField.extend({ * @private */ _render: function () { - var class_name = this.value ? 'o_toggle_button_success' : 'text-muted'; - this.$('i').attr('class', ('fa fa-circle ' + class_name)); + var className = this.value ? 'o_toggle_button_success' : 'text-muted'; + this.$('i').addClass('fa fa-circle ' + className); var title = this.value ? this.attrs.options.active : this.attrs.options.inactive; this.$el.attr('title', title); }, @@ -1747,7 +1737,6 @@ var FieldToggleBoolean = AbstractField.extend({ event.stopPropagation(); this._setValue(!this.value); }, - }); var JournalDashboardGraph = AbstractField.extend({ @@ -1891,7 +1880,7 @@ var FieldDomain = AbstractField.extend({ events: _.extend({}, AbstractField.prototype.events, { "click .o_domain_show_selection_button": "_onShowSelectionButtonClick", - "click .o_form_field_domain_dialog_button": "_onDialogEditButtonClick", + "click .o_field_domain_dialog_button": "_onDialogEditButtonClick", }), custom_events: { "domain_changed": "_onDomainSelectorValueChange", @@ -1907,7 +1896,7 @@ var FieldDomain = AbstractField.extend({ this.inDialog = !!this.nodeOptions.in_dialog; this.fsFilters = this.nodeOptions.fs_filters || {}; - this.className = "o_form_field_domain"; + this.className = "o_field_domain"; if (this.mode === "edit") { this.className += " o_edit_mode"; } @@ -2190,7 +2179,7 @@ var AceEditor = DebouncedField.extend({ return { DebouncedField: DebouncedField, - EmailWidget: EmailWidget, + FieldEmail: FieldEmail, FieldBinaryFile: FieldBinaryFile, FieldBinaryImage: FieldBinaryImage, FieldBoolean: FieldBoolean, diff --git a/addons/web/static/src/js/fields/field_registry.js b/addons/web/static/src/js/fields/field_registry.js index 41889fcfa85..dcd8f7acd48 100644 --- a/addons/web/static/src/js/fields/field_registry.js +++ b/addons/web/static/src/js/fields/field_registry.js @@ -29,7 +29,7 @@ registry .add('float', basic_fields.FieldFloat) .add('char', basic_fields.FieldChar) .add('handle', basic_fields.HandleWidget) - .add('email', basic_fields.EmailWidget) + .add('email', basic_fields.FieldEmail) .add('phone', basic_fields.FieldPhone) .add('url', basic_fields.UrlWidget) .add('image', basic_fields.FieldBinaryImage) diff --git a/addons/web/static/src/js/fields/field_utils.js b/addons/web/static/src/js/fields/field_utils.js index afc15b7a882..508d97b131c 100644 --- a/addons/web/static/src/js/fields/field_utils.js +++ b/addons/web/static/src/js/fields/field_utils.js @@ -35,13 +35,16 @@ var _t = core._t; * @returns {jQueryElement} */ function formatBoolean(value) { - var $input = $('<input type="checkbox">') - .prop('checked', value) - .prop('disabled', true); - return $('<div>') - .addClass('o_checkbox') - .append($input) - .append($('<span>')); + var $input = $('<input/>', { + type: 'checkbox', + }).prop({ + checked: value, + disabled: true, + }); + var $div = $('<div/>', { + class: 'o_checkbox', + }); + return $div.append($input, '<span/>'); } /** @@ -342,7 +345,7 @@ function parseDateTime(value, field, options) { var pattern2 = datePatternWoZero + ' ' + timePatternWoZero; var datetime; if (options && options.isUTC) { - // phatomjs crash if we don't use this format + // phatomjs crash if we don't use this format datetime = moment.utc(value.replace(' ', 'T') + 'Z'); } else { datetime = moment.utc(value, [pattern1, pattern2, moment.ISO_8601], true); diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 28d790b16c4..d7e65f5c4bf 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -81,9 +81,9 @@ var FieldMany2One = AbstractField.extend({ 'search_create_popup': '_onSearchCreatePopup', }, events: _.extend({}, AbstractField.prototype.events, { - 'click .o_form_input': '_onInputClick', - 'focusout .o_form_input': '_onInputFocusout', - 'keyup .o_form_input': '_onInputKeyup', + 'click input': '_onInputClick', + 'focusout input': '_onInputFocusout', + 'keyup input': '_onInputKeyup', 'click .o_external_button': '_onExternalButtonClick', 'click': '_onClick', }), @@ -106,7 +106,7 @@ var FieldMany2One = AbstractField.extend({ // what is 'this.floating' for? add a comment! this.floating = false; - this.$input = this.$('.o_form_input'); + this.$input = this.$('input'); this.$external_button = this.$('.o_external_button'); return this._super.apply(this, arguments); }, @@ -713,7 +713,7 @@ var FieldX2Many = AbstractField.extend({ onFailure: def.reject.bind(def), }); } else { - self.renderer.setRowMode(recordID, 'readonly', true); + self.renderer.setRowMode(recordID, 'readonly'); def.resolve(); } }); @@ -819,7 +819,7 @@ var FieldX2Many = AbstractField.extend({ }); var FieldOne2Many = FieldX2Many.extend({ - className: 'o_form_field_one2many', + className: 'o_field_one2many', supportedFieldTypes: ['one2many'], //-------------------------------------------------------------------------- @@ -937,7 +937,7 @@ var FieldOne2Many = FieldX2Many.extend({ }); var FieldMany2Many = FieldX2Many.extend({ - className: 'o_form_field_many2many', + className: 'o_field_many2many', supportedFieldTypes: ['many2many'], /** @@ -1019,7 +1019,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({ events: { 'click .o_attach': '_onAttach', 'click .oe_delete': '_onDelete', - 'change .o_form_input_file': '_onFileChanged', + 'change .o_input_file': '_onFileChanged', }, /** * @constructor @@ -1102,7 +1102,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({ _onAttach: function () { // This widget uses a hidden form to upload files. Clicking on 'Attach' // will simulate a click on the related input. - this.$('.o_form_input_file').click(); + this.$('.o_input_file').click(); }, /** * @private @@ -1196,7 +1196,7 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({ var FieldMany2ManyTags = AbstractField.extend({ tag_template: "FieldMany2ManyTag", - className: "o_form_field o_form_field_many2manytags", + className: "o_field_many2manytags", supportedFieldTypes: ['many2many'], custom_events: { field_changed: '_onFieldChanged', @@ -1204,13 +1204,24 @@ var FieldMany2ManyTags = AbstractField.extend({ }, events: _.extend({}, AbstractField.prototype.events, { 'click .o_delete': '_onDeleteTag', - 'keydown .o_form_field_many2one input': '_onKeyDown', + 'keydown .o_field_many2one input': '_onKeyDown', }), fieldsToFetch: { color: {type: 'integer'}, display_name: {type: 'char'}, }, + /** + * @constructor + */ + init: function () { + this._super.apply(this, arguments); + + if (this.mode === 'edit') { + this.className += ' o_input'; + } + }, + //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- @@ -1310,7 +1321,7 @@ var FieldMany2ManyTags = AbstractField.extend({ this.many2one._getSearchBlacklist = function () { return self.value.res_ids; }; - this.many2one.appendTo(this.$el); + return this.many2one.appendTo(this.$el); }, /** * @private @@ -1445,7 +1456,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({ var KanbanFieldMany2ManyTags = FieldMany2ManyTags.extend({ _render: function () { var self = this; - this.$el.addClass('o_form_field_many2manytags o_kanban_tags'); + this.$el.addClass('o_field_many2manytags o_kanban_tags'); _.each(this.value.data, function (m2m) { // 10th color is invisible if ('color' in m2m.data && m2m.data.color !== 10) { 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 e150b0b2dd0..25ba02530be 100644 --- a/addons/web/static/src/js/views/basic/basic_renderer.js +++ b/addons/web/static/src/js/views/basic/basic_renderer.js @@ -52,7 +52,7 @@ var BasicRenderer = AbstractRenderer.extend({ if (!canBeSaved) { invalidFields.push(widget.name); } - widget.$el.toggleClass('o_form_invalid', !canBeSaved); + widget.$el.toggleClass('o_field_invalid', !canBeSaved); }); return invalidFields; }, @@ -249,9 +249,9 @@ var BasicRenderer = AbstractRenderer.extend({ } // Toggle modifiers CSS classes if necessary - element.$el.toggleClass("o_form_invisible", !!modifiers.invisible); - element.$el.toggleClass("o_readonly", !!modifiers.readonly); - element.$el.toggleClass("o_form_required", !!modifiers.required); + element.$el.toggleClass("o_invisible_modifier", !!modifiers.invisible); + element.$el.toggleClass("o_readonly_modifier", !!modifiers.readonly); + element.$el.toggleClass("o_required_modifier", !!modifiers.required); // Call associated callback if (element.callback) { @@ -495,7 +495,15 @@ var BasicRenderer = AbstractRenderer.extend({ // Update the modifiers registration by associating the widget and by // giving the modifiers options now (as the potential callback is // associated to new widget) - this._registerModifiers(node, record, widget, modifiersOptions); + this._registerModifiers(node, record, widget, _.extend({ + callback: (function (element, modifiers, record) { + element.$el.toggleClass('o_field_empty', !!( + record.data.id + && (modifiers.readonly || this.mode === 'readonly') + && !element.widget.isSet() + )); + }).bind(this), + }, modifiersOptions || {})); return widget; }, diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js index 20244f12e95..f6bcbd49eeb 100644 --- a/addons/web/static/src/js/views/form/form_renderer.js +++ b/addons/web/static/src/js/views/form/form_renderer.js @@ -8,10 +8,6 @@ var core = require('web.core'); var _t = core._t; var qweb = core.qweb; -var FIELD_CLASSES = { - 'one2many': 'o_field_one2many', -}; - var FormRenderer = BasicRenderer.extend({ className: "o_form_view", /** @@ -27,7 +23,7 @@ var FormRenderer = BasicRenderer.extend({ //-------------------------------------------------------------------------- /** - * Extend the method so that labels also receive the 'o_form_invalid' class + * Extend the method so that labels also receive the 'o_field_invalid' class * if necessary. * * @override @@ -40,14 +36,14 @@ var FormRenderer = BasicRenderer.extend({ var fieldNames = this._super.apply(this, arguments); var $labels = this.$('label'); - $labels.removeClass('o_form_invalid'); + $labels.removeClass('o_field_invalid'); _.each(fieldNames, function (fieldName) { var idForLabel = self.idsForLabels[fieldName]; if (idForLabel) { $labels .filter('[for=' + idForLabel + ']') - .addClass('o_form_invalid'); + .addClass('o_field_invalid'); } }); return fieldNames; @@ -66,7 +62,7 @@ var FormRenderer = BasicRenderer.extend({ _.each(resetWidgets, function (widget) { self._setIDForLabel(widget, self.idsForLabels[widget.name]); }); - return resetWidgets + return resetWidgets; }); }, /** @@ -105,7 +101,7 @@ var FormRenderer = BasicRenderer.extend({ var name = $notebook.data('name'); if (name in state) { var $page = $notebook.find('> ul > li').eq(state[name]); - if (!$page.hasClass('o_form_invisible')) { + if (!$page.hasClass('o_invisible_modifier')) { $page.find('a[data-toggle="tab"]').click(); } } @@ -138,15 +134,6 @@ var FormRenderer = BasicRenderer.extend({ //-------------------------------------------------------------------------- /** - * Adds the adequate classnames to a field widget's $el. - * - * @private - * @param {Object} widget a field widget - */ - _addFieldClassNames: function (widget) { - widget.$el.addClass('o_form_field'); // TODO will be removed in the CSS update - }, - /** * @private * @param {jQueryElement} $el * @param {Object} node @@ -207,7 +194,7 @@ var FormRenderer = BasicRenderer.extend({ } }); var buttons_partition = _.partition(buttons, function ($button) { - return $button.is('.o_form_invisible'); + return $button.is('.o_invisible_modifier'); }); var invisible_buttons = buttons_partition[0]; var visible_buttons = buttons_partition[1]; @@ -261,22 +248,8 @@ var FormRenderer = BasicRenderer.extend({ * @returns {AbstractField} */ _renderFieldWidget: function (node, record, options, modifiersOptions) { - var self = this; - modifiersOptions = _.extend({ - callback: function (element, modifiers, record) { - element.$el.toggleClass('o_form_field_empty', !!( // FIXME condition is evaluated twice (label AND widget...) - record.data.id - && (modifiers.readonly || self.mode === 'readonly') - && !element.widget.isSet() - )); - }, - }, modifiersOptions || {}); - - var widget = this._super(node, record, options, modifiersOptions); + var widget = this._super.apply(this, arguments); this._setIDForLabel(widget, this._getIDForLabel(node.attrs.name)); - - widget.$el.addClass(FIELD_CLASSES[record.fields[node.attrs.name].type]); - this._addFieldClassNames(widget); this._handleAttributes(widget.$el, node); if (JSON.parse(node.attrs.default_focus || "0")) { this.defaultFocusField = widget; @@ -344,7 +317,7 @@ var FormRenderer = BasicRenderer.extend({ }); this._registerModifiers(node, this.state, $label, { callback: function (element, modifiers, record) { - element.$el.toggleClass('o_form_label_empty', !!( + element.$el.toggleClass('o_form_label_empty', !!( // FIXME condition is evaluated twice (label AND widget...) record.data.id && (modifiers.readonly || self.mode === 'readonly') && !widget.isSet() // getting like this because it could have been re-rendered... @@ -656,7 +629,7 @@ var FormRenderer = BasicRenderer.extend({ if (modifiers.invisible && element.$el.hasClass('active')) { element.$el.removeClass('active'); tab.$page.removeClass('active'); - var $firstVisibleTab = $headers.find('li:not(.o_form_invisible):first()'); + var $firstVisibleTab = $headers.find('li:not(.o_invisible_modifier):first()'); $firstVisibleTab.addClass('active'); $pages.find($firstVisibleTab.find('a').attr('href')).addClass('active'); } diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js index 3d34b80f846..1b662fa46af 100644 --- a/addons/web/static/src/js/views/list/list_editable_renderer.js +++ b/addons/web/static/src/js/views/list/list_editable_renderer.js @@ -29,7 +29,7 @@ ListRenderer.include({ 'click tbody tr:not(.o_data_row)': '_onEmptyRowClick', 'click tfoot': '_onFooterClick', 'click tr .o_list_record_delete': '_onTrashIconClick', - 'click .o_form_field_x2many_list_row_add a': '_onAddRecord', + 'click .o_field_x2many_list_row_add a': '_onAddRecord', }), /** * @override @@ -90,31 +90,6 @@ ListRenderer.include({ return this._super(recordID); }, /** - * @see BasicRenderer.confirmChange - * - * We also react to changes by adding the 'o_field_dirty' css class, - * which changes its style to a visible orange outline. It allows the user - * to have a visual feedback on which fields changed, and on which fields - * have been saved. - * - * @todo maybe should be a basic behavior - * - * @override - * @param {Object} state - a record resource (the new full state) - * @param {string} id - the local id for the changed record - * @param {string[]} fields - list of modified fields - * @param {OdooEvent} e - the event that triggered the change - * @returns {Deferred} - */ - confirmChange: function (state, id, fields, e) { - return this._super.apply(this, arguments).then(function (resetWidgets) { - _.each(resetWidgets, function (widget) { - var $td = widget.$el.parent(); - $td.addClass('o_field_dirty'); - }); - }); - }, - /** * This method is called by the controller when the user has clicked 'save', * and the model as actually saved the current changes. We then need to * set the correct values for each cell. The difference with confirmChange @@ -172,9 +147,8 @@ ListRenderer.include({ * * @param {string} recordID * @param {string} mode - * @param {boolean} [keepDirtyFlag=false] */ - setRowMode: function (recordID, mode, keepDirtyFlag) { + setRowMode: function (recordID, mode) { var self = this; var rowIndex = _.findIndex(this.state.data, {id: recordID}); if (rowIndex < 0) { @@ -185,12 +159,18 @@ ListRenderer.include({ this.currentRow = editMode ? rowIndex : null; var $row = this.$('.o_data_row:nth(' + rowIndex + ')'); - $row.toggleClass('o_selected_row', editMode); if (editMode) { // Instantiate column widgets and destroy potential readonly ones var oldWidgets = _.clone(this.allFieldWidgets[record.id]); var $tds = $row.children('.o_data_cell'); + // Force the size of each cell to its current value so that it + // won't change if its content changes, to prevent the view from + // flickering + $tds.each(function () { + var $td = $(this); + $td.css({width: $td.outerWidth()}); + }); _.each(this.columns, function (node, colIndex) { var $td = $tds.eq(colIndex); var $newTd = self._renderBodyCell(record, node, colIndex, { @@ -203,18 +183,16 @@ ListRenderer.include({ self._unregisterModifiersElement(node, record, $td.children()); } - // Force the width of each cell to its current value so that it - // won't change if its content changes, to prevent the view from - // flickering - $td.width($td.width()); $td.empty().append($newTd.contents()); }); _.each(oldWidgets, this._destroyFieldWidget.bind(this, record)); } else { for (var colIndex = 0; colIndex < this.columns.length; colIndex++) { - this._setCellValue(rowIndex, colIndex, keepDirtyFlag || false); + this._setCellValue(rowIndex, colIndex); } } + + $row.toggleClass('o_selected_row', editMode); // Toggle here so that style is applied at the end }, //-------------------------------------------------------------------------- @@ -310,7 +288,7 @@ ListRenderer.include({ var $a = $('<a href="#">').text(_t("Add an item")); var $td = $('<td>') .attr('colspan', this._getNumberOfCols()) - .addClass('o_form_field_x2many_list_row_add') + .addClass('o_field_x2many_list_row_add') .append($a); var $tr = $('<tr>').append($td); $rows.push($tr); @@ -398,17 +376,13 @@ ListRenderer.include({ * * @param {integer} rowIndex * @param {integer} colIndex - * @param {boolean} keepDirtyFlag */ - _setCellValue: function (rowIndex, colIndex, keepDirtyFlag) { + _setCellValue: function (rowIndex, colIndex) { var record = this.state.data[rowIndex]; var node = this.columns[colIndex]; var $oldTd = this.$('.o_data_row:nth(' + rowIndex + ') > .o_data_cell:nth(' + colIndex + ')'); var $newTd = this._renderBodyCell(record, node, colIndex, {mode: 'readonly'}); - if (keepDirtyFlag && $oldTd.hasClass('o_field_dirty')) { - $newTd.addClass('o_field_dirty'); - } this._unregisterModifiersElement(node, record, $oldTd); $oldTd.replaceWith($newTd); diff --git a/addons/web/static/src/js/widgets/switch_company_menu.js b/addons/web/static/src/js/widgets/switch_company_menu.js index 8bea91a5a97..c27a6d82603 100644 --- a/addons/web/static/src/js/widgets/switch_company_menu.js +++ b/addons/web/static/src/js/widgets/switch_company_menu.js @@ -34,9 +34,9 @@ var SwitchCompanyMenu = Widget.extend({ _.each(session.user_companies.allowed_companies, function(company) { var a = ''; if (company[0] === session.user_companies.current_company[0]) { - a = '<i class="fa fa-check o_current_company"></i>'; + a = '<i class="fa fa-check mr8"></i>'; } else { - a = '<span class="o_company"/>'; + a = '<span class="mr24"/>'; } companies_list += '<li><a href="#" data-menu="company" data-company-id="' + company[0] + '">' + a + company[1] + '</a></li>'; }); diff --git a/addons/web/static/src/less/animation.less b/addons/web/static/src/less/animation.less index 4aeabc4acc4..c9fe2ae7af4 100644 --- a/addons/web/static/src/less/animation.less +++ b/addons/web/static/src/less/animation.less @@ -1,4 +1,4 @@ -/************** DEFINITION of ANIMATIONS *************/ +/************** DEFINITION of ANIMATIONS **************/ // 'marked' effects @keyframes markAnim { 0% { @@ -145,51 +145,32 @@ } } -/************** MIXINS for ANIMATIONS *************/ +/************** MIXINS for ANIMATIONS **************/ .o-display-marked(@content, @top, @left, @color) { - position: absolute; - top: @top; - left: @left; + .o-position-absolute(@top: @top, @left: @left); font-size: 300px; font-family: "FontAwesome"; content: @content; color: @color; - animation: markAnim ease-in-out 1s; - animation-iteration-count: 1; - transform-origin: 50% 50%; - animation-fill-mode:forwards; /*when the spec is finished*/ - -webkit-animation: markAnim ease-in-out 1s; - -webkit-animation-iteration-count: 1; - -webkit-transform-origin: 50% 50%; - -webkit-animation-fill-mode:forwards; /*Chrome 16+, Safari 4+*/ - -moz-animation: markAnim ease-in-out 1s; - -moz-animation-iteration-count: 1; - -moz-transform-origin: 50% 50%; - -moz-animation-fill-mode:forwards; /*FF 5+*/ - -o-animation: markAnim ease-in-out 1s; - -o-animation-iteration-count: 1; - -o-transform-origin: 50% 50%; - -o-animation-fill-mode:forwards; /*Not implemented yet*/ - -ms-animation: markAnim ease-in-out 1s; - -ms-animation-iteration-count: 1; - -ms-transform-origin: 50% 50%; - -ms-animation-fill-mode:forwards; /*IE 10+*/ + .o-transform-origin(); + .o-animation(markAnim, 1s, ease-in-out, 0s, 1, normal, forwards); - @media (max-width: 992px) { + @media (max-width: @screen-sm-max) { left: 40%; font-size: 30vw; } } - -/************** USAGE of ANIMATIONS *************/ +/************** USAGE of ANIMATIONS **************/ // Animation on wow button +// TODO the only difference here is the "content" property, just make an +// 'o_wow' class for the other properties to avoid generating useless CSS .o_wow_thumbs:after { - .o-display-marked("\f164", 20%, 40%, #21b799); + .o-display-marked("\f164", 20%, 40%, @odoo-brand-optional); } .o_wow_peace:after { - .o-display-marked("\f118", 20%, 40%, #21b799); + .o-display-marked("\f118", 20%, 40%, @odoo-brand-optional); } .o_wow_heart:after { - .o-display-marked("\f004", 20%, 40%, #21b799); + .o-display-marked("\f004", 20%, 40%, @odoo-brand-optional); } diff --git a/addons/web/static/src/less/control_panel.less b/addons/web/static/src/less/control_panel.less index e2635af43d4..83048112815 100644 --- a/addons/web/static/src/less/control_panel.less +++ b/addons/web/static/src/less/control_panel.less @@ -1,63 +1,109 @@ +@breadcrumb-height: 30px; + .o_control_panel { + .o-flex-display(); + .o-flex-flow(row, wrap); + border-bottom: 1px solid @odoo-main-color-muted; .o-webclient-padding(@top: 10px, @bottom: 10px); background-color: @odoo-control-panel-background-color; - border-bottom: 1px solid @odoo-main-color-muted; - .breadcrumb { - font-size: 18px; + + > .breadcrumb { + width: 50%; margin: 0px; - > li > a { - color: @odoo-brand-optional; - cursor: pointer; - &:hover { - color: darken(@odoo-brand-optional, 10%); - text-decoration: none; + font-size: 18px; + + > li { + .o-text-overflow(@max-width: 90%); + + > a { + color: @odoo-brand-optional; + cursor: pointer; + + &:hover { + color: darken(@odoo-brand-optional, 10%); + text-decoration: none; + } } } } - // Sidebar - .o_cp_sidebar { - padding-right: 10px; + &.o_breadcrumb_full > .breadcrumb { + width: 100%; + } - .o_hidden_input_file { - position: relative; - input.o_form_input_file { - position: absolute; - top: 1px; - opacity: 0; - width: 100%; - height: 26px; - } - .o_form_binary_form span { - padding: 3px 25px; - color: @btn-default-color; + > .o_cp_searchview { + width: 50%; + min-height: @breadcrumb-height; + } + + .btn.o_enable_searchview { + width: 10%; + margin-left: 2%; + padding: 0px; + } + + > .o_cp_left { + .o-flex-display(); + .o-justify-content(space-between); + width: 50%; + margin-top: 5px; + + > .o_cp_sidebar { + padding-right: 10px; + + .o_hidden_input_file { + position: relative; + input.o_input_file { + position: absolute; + top: 1px; + opacity: 0; + width: 100%; + height: 26px; + } + .o_form_binary_form span { + padding: 3px 25px; + color: @btn-default-color; + } + .o_form_binary_form:hover { + background-color: @table-bg-hover; + } } - .o_form_binary_form:hover { - background-color: @table-bg-hover; + .o_sidebar_delete_attachment { + padding: 0px; + position: absolute; + top: 5px; + right: 10px; } } - .o_sidebar_delete_attachment { - padding: 0px; - position: absolute; - top: 5px; - right: 10px; - } } - // Pager - .o_cp_pager { - text-align: center; - padding-left: 5px; - .user-select(none); - } + > .o_cp_right { + .o-flex-display(); + width: 50%; + margin-top: 5px; + + > .o_cp_pager { + margin: auto 0 auto auto; + padding-left: 5px; + text-align: center; + .user-select(none); + } - // View Switcher - .o_cp_switch_buttons { - padding-left: 5px; + > .o_cp_switch_buttons { + padding-left: 5px; + } } } .o_x2m_control_panel { + .o-flex-display(); + .o-flex-flow(row, wrap); + + .o_cp_buttons, .o_cp_pager { + .o-flex-display(); + margin-right: auto; + } + .o_cp_buttons > div { margin-top: 5px; } @@ -68,7 +114,14 @@ display: inline-block; width: 60px; text-align: right; + &:focus { outline: none; } } + +@media print { + .o_control_panel { + display: none; + } +} diff --git a/addons/web/static/src/less/control_panel_layout.less b/addons/web/static/src/less/control_panel_layout.less deleted file mode 100644 index 92f8397bca4..00000000000 --- a/addons/web/static/src/less/control_panel_layout.less +++ /dev/null @@ -1,70 +0,0 @@ -@breadcrumb-height: 30px; - -.o_control_panel { - .o-flex-display(); - .o-flex-flow(row, wrap); - - .breadcrumb { - width: 50%; - - > li { - .o_text_overflow; - max-width: 90%; - display: inline-block; - } - } - - &.o_breadcrumb_full { - .breadcrumb { - width: 100%; - } - } - - .o_cp_searchview { - width: 50%; - min-height: @breadcrumb-height; - } - - .btn.o_enable_searchview { - width: 10%; - margin-left: 2%; - padding: 0px; - } - - .o_cp_left { - width: 50%; - margin-top: 5px; - .o-flex-display(); - .o-justify-content(space-between); - } - - .o_cp_right { - width: 50%; - margin-top: 5px; - .o-flex-display(); - - .o_cp_pager { - margin: auto 0 auto auto; - } - } -} - -.o_x2m_control_panel { - .o-flex-display(); - .o-flex-flow(row, wrap); - - .o_cp_buttons { - .o-flex-display(); - margin-right: auto; - } - .o_cp_pager { - .o-flex-display(); - margin-left: auto; - } -} - -@media print { - .o_control_panel { - display: none; - } -} diff --git a/addons/web/static/src/less/fields.less b/addons/web/static/src/less/fields.less new file mode 100644 index 00000000000..329b4f62fbd --- /dev/null +++ b/addons/web/static/src/less/fields.less @@ -0,0 +1,367 @@ +// +// This file regroups all the rules which apply to field widgets wherever they +// are in the DOM, in both community and enterprise versions. +// + +// Invalid +.o_field_invalid { + &.o_input, .o_input, &.o_form_label { + color: @brand-danger!important; + border-color: @brand-danger!important; // enterprise o_required_modifier rule overrides this without !important + } +} + +// Empty +.o_field_empty { + display: none!important; +} + +// Numbers +.o_field_number { + white-space: nowrap; +} + +//------------------------------------------------------------------------------ +// Fields +//------------------------------------------------------------------------------ + +.o_field_widget { + display: inline-block; + + // Block fields + &.note-editor, &.oe_form_field_html, &.oe_form_field_html_text, &.oe_form_field_text, &.o_view_manager_content, &.o_field_domain { + display: block; + } + + // Flex fields (inline) + &.o_field_many2one, &.o_field_radio, &.o_field_many2manytags, &.o_field_percent_pie, &.o_field_monetary, &.o_field_binary_file { + @media (min-width: @screen-sm-min) { + .o-inline-flex-display(); + } + > span, > button { + .o-flex(0, 0, auto); + } + } + + // Dropdowns input (many2one, ...) + .o_input_dropdown { + .o-flex(1, 0, auto); + position: relative; + width: 100%; + + > input { + height: 100%; + padding-right: 15px; + cursor: pointer; + } + + .o_dropdown_button { + .o-position-absolute(0, 0); + pointer-events: none; + &:after { + .o-caret-down; + } + } + } + + // Input in field + input[type="text"] { + display: inline-block; + } + + // Text + &.o_field_text, &.oe_form_field_text .oe_form_text_content { + width: 100%; + white-space: pre-wrap; + } + + // Monetary + &.o_field_monetary { + &.o_input { + .o-align-items(baseline); + + > input { + width: 100px; + .o-flex(1, 0, auto); + } + } + } + + // Many2many tags + &.o_field_many2manytags { + .o-flex-flow(row, wrap); + .o-align-items(baseline); + + > .o_field_widget { + .o-flex(1, 0, 100px); + position: initial; + max-width: 100%; + } + + > .badge { + .o-flex(0, 0, auto); + border: 0; + font-size: 12px; + color: white; + cursor: pointer; + + &.o_tag_color_0 { background-color: #4D4D4D; } + &.o_tag_color_1 { background-color: #61BD4F; } + &.o_tag_color_2 { background-color: #F2D600; } + &.o_tag_color_3 { background-color: #FFAB4A; } + &.o_tag_color_4 { background-color: #EB5A46; } + &.o_tag_color_5 { background-color: #875A7B; } + &.o_tag_color_6 { background-color: #0079BF; } + &.o_tag_color_7 { background-color: #00C2E0; } + &.o_tag_color_8 { background-color: #4CD98E; } + &.o_tag_color_9 { background-color: #FF80CE; } + &.o_tag_color_10 { background-color: #B6BBBF; } + + > .o_badge_text { + .o-text-overflow(inline-block); + max-width: 200px; + } + + > ul { + @colored-tag-width: 45px; + width: 5*@colored-tag-width + 3px; + > li { + float: left; + color: black; + > span { + border-radius: 6px; + width: @colored-tag-width; + height: 30px; + display: inline-block; + border: 2px solid white; + cursor: pointer; + padding: 0; + + &:hover { + opacity: 0.8; + } + } + } + > li:last-child { + margin-top: 7px; + cursor: auto; + } + } + + .o_delete { + cursor: pointer; + } + } + } + + // Stars + &.o_priority { + display: inline-block; + padding: 0; + margin: 0; + vertical-align: middle; + > .o_priority_star { + display: inline-block; + font-size: 1.35em; + &:hover, &:focus { + text-decoration: none; + outline: none; + } + + + .o_priority_star { + padding-left: 5px; + } + + &.fa-star-o { + color: @odoo-main-color-muted; + } + &.fa-star { + color: gold; + } + } + } + + // Status + &.o_selection .o_status { + display: inline-block; + height: 12px; + width: 12px; + border-radius: 6px; + vertical-align: middle; + + background-color: @odoo-brand-secondary; + + &.o_status_green { + background-color: @brand-success; + } + &.o_status_red { + background-color: @brand-danger; + } + } + + // Specific success color for toggle_button widget + .fa.o_toggle_button_success { + color: @brand-success; + } + + // Many2One + &.o_field_many2one { + .o-inline-flex-display(); + > span, > button { + .o-flex(0, 0, auto); + } + } + + // Handle widget + &.o_row_handle { + cursor: ns-resize; + } + + // Radio buttons + &.o_field_radio { + .o_radio_input { + outline: none; + } + + .o_radio_item { + .o-flex(0, 0, auto); + .o-flex-display(); + .o-align-items(center); + + > input { + .o-flex(0, 0, auto); + margin: 0 @odoo-form-spacing-unit 0 0; + } + > label { + margin: 0; + } + } + + &.o_horizontal { + .o_radio_item { + margin-right: @odoo-form-spacing-unit * 2; + } + } + + &.o_vertical { + .o-flex-flow(column, nowrap); + .o_radio_item { + margin-bottom: @odoo-form-spacing-unit; + } + } + } + + // Percent pie + &.o_field_percent_pie { + .o-align-items(center); + + > .o_pie { + position: relative; + margin-right: 10px; + border-radius: 100%; + overflow: hidden; + background-color: @odoo-brand-optional; + + &:after { // Outside pie border to go over border-radius irregularities + content: " "; + .o-position-absolute(0, 0); + width: 100%; + height: 100%; + border-radius: 100%; + } + + .o_mask { + .o-position-absolute(0, 0); + .o-transform-origin(0); + width: 50%; + height: 100%; + background-color: @odoo-view-background-color; + &.o_full { + background-color: inherit; + } + } + + .o_pie_value { + .o-flex-display(); + .o-justify-content(center); + .o-align-items(center); + + border-radius: 100%; + + font-weight: 700; + color: @odoo-brand-primary; + } + } + } + + // Ace editor + &.o_ace_view_editor { + width: 100%; + .ace-view-editor { + height: 300px; + padding: 0 1em; + } + } + + // Image + &.o_field_image { + position: relative; + + .o_form_image_controls { + .o-position-absolute(0, 0); + width: 100%; + + color: white; + background-color: @odoo-brand-optional; + opacity: 0; + transition: opacity ease 400ms; + + > .fa { + margin: 5px; + cursor: pointer; + } + } + @media (max-width: @screen-xs-min) { + .o_form_image_controls{ + position: initial; + opacity: 1; + > .fa{ + width: 50%; + padding: 6px; + margin: 0px; + text-align: center; + &.o_select_file_button{ + background: @odoo-brand-optional; + } + &.o_clear_file_button{ + background: @brand-danger; + } + } + } + } + + &:hover .o_form_image_controls { + opacity: 0.8; + } + } + + // Input loading/file + .o_form_binary_progress, .o_hidden_input_file .o_input_file { + display: none; + } + + // Domain + &.o_field_domain { + > .o_field_domain_panel { + margin-top: 8px; + } + &.o_inline_mode.o_edit_mode { + position: relative; + + > .o_field_domain_panel { + .o-position-absolute(0, 0); + margin-top: 0; + } + } + } +} diff --git a/addons/web/static/src/less/fields_extra.less b/addons/web/static/src/less/fields_extra.less new file mode 100644 index 00000000000..79d9628116d --- /dev/null +++ b/addons/web/static/src/less/fields_extra.less @@ -0,0 +1,58 @@ +// +// This file regroups all the rules which apply to field widgets wherever they +// are in the DOM, in the community version. +// + +// Required +.o_required_modifier { + &.o_input, .o_input { + background-color: #D2D2FF; + } +} + +//------------------------------------------------------------------------------ +// Fields +//------------------------------------------------------------------------------ + +.o_field_widget { + // Dropdowns input carret + .o_input_dropdown .o_dropdown_button { + .o-position-absolute(2px, 4px); + } + + // Many2one + &.o_field_many2one .o_external_button { + padding: 0; + margin-left: 2px; + font-size: 19px; + color: #7C7BAD; + border: none; + &:hover { + background-color: transparent; + } + } + + // Percent pie field + &.o_field_percent_pie { + @pie-dimension: 34px; + @pie-ring-width: 4px; + + .o_pie { + width: @pie-dimension; + height: @pie-dimension; + margin-left: 5px; + + &:after { // Outside pie border to go over border-radius irregularities + border: 1px solid @odoo-brand-primary; + } + + .o_pie_value { + .o-position-absolute(@pie-ring-width, @pie-ring-width); + width: @pie-dimension - 2 * @pie-ring-width; + height: @pie-dimension - 2 * @pie-ring-width; + border: 1px solid white; + background-color: white; + } + } + } +} diff --git a/addons/web/static/src/less/form_view.less b/addons/web/static/src/less/form_view.less index f8a221672d8..f7c5616342a 100644 --- a/addons/web/static/src/less/form_view.less +++ b/addons/web/static/src/less/form_view.less @@ -1,10 +1,7 @@ .o_form_view { background-color: @odoo-view-background-color; - // Utility classes (+ oe_edit_only, oe_read_only, o_label_nowrap, o_text_overflow) - .o_form_invisible, .o_form_field_empty { - display: none!important; - } + // Utility classes .oe_form_box_info { .bg-info; .o-webclient-padding(@top: 5px, @bottom: 5px); @@ -21,11 +18,72 @@ .oe_grey { opacity: 0.5; } + .oe_inline { + width: auto!important; + @media (min-width: @screen-xs-min) { + &.o_inner_group { + width: 1px!important; + } + } + } + .oe_left { + .oe_inline; + float: left!important; + } + .oe_right { + .oe_inline; + float: right!important; + } + + @media (min-width: @screen-xs-min) { + .o_row { + &, &.o_field_widget { // Some field may want to use o_row as root and these rules must prevalue + .o-flex-display(); + width: auto!important; + } + + .o-align-items(baseline); + min-width: 50px; + margin: 0 -@odoo-form-spacing-unit/2; + + > div, > span, > button, > label, > a, > input { // > * did not add a level of priority to the rule + .o-flex(0, 0, auto); + width: auto!important; + margin-right: @odoo-form-spacing-unit/2; + margin-left: @odoo-form-spacing-unit/2; + } + + > .o_row { + margin: 0; + } + > .btn { + padding-top: 0; + padding-bottom: 0; + } + > .o_field_boolean { + .o-align-self(center); + } + } + + .o_row .o_field_many2one, .o_field_many2one.oe_inline { + &.o_with_button:not(:last-child) { // If invisible element as last child, this line has no effect but that's not very important + margin-right: (35px + (@odoo-form-spacing-unit/2)); + } + } + } + + .o_row > div > .o_field_widget { + width: 100%; + } // Readonly specific rules &.o_form_readonly { .oe_edit_only { - .o_form_invisible; + display: none!important; + } + + .o_row, .o_row > div { + display: inline-block; } .o_form_uri { // FIXME maybe global? @@ -47,42 +105,63 @@ // Editable specific rules &.o_form_editable { .oe_read_only { - .o_form_invisible; + display: none!important; } - .o_form_field_many2manytags { - .o-input(); - - > .o_form_field { - .o-flex(1, 0, 100px); - position: initial; - max-width: 100%; - - > .o_form_input_dropdown > .o_form_input { - border-style: none!important; - } - } + .oe_title { + max-width: @container-sm - (2 * @odoo-horizontal-padding); } - .o_form_field_monetary { - .o-input(); - .o-align-items(baseline); + @media (min-width: @screen-xs-min) { + .o_row { + > .o_field_widget, > div { + .o-flex(1, 1, auto); + width: 0!important; // 3rd flex argument does not work with input (must be auto and real width 0) - > .o_form_input { - border-style: none!important; - width: 100px; - .o-flex(1, 0, auto); + &.o_field_boolean, &.o_priority { + .o-flex(0, 0, auto); + width: auto!important; + } + } } } } - // Header containing status/workflow buttons + // Statusbar .o_form_statusbar { - background-color: @odoo-view-background-color; + .o-flex(0, 0, auto); position: relative; // Needed for the "More" dropdown + .o-flex-display(); + .o-justify-content(space-between); + padding-left: @odoo-horizontal-padding; border-bottom: 1px solid @odoo-brand-secondary; + background-color: @odoo-view-background-color; + + > .o_statusbar_buttons, > .o_statusbar_status { + .o-flex-display(); + .o-align-items(center); + .o-align-content(space-around); + } + + > .o_field_widget { + .o-align-self(center); + margin-bottom: 0px; + } + + > .o_statusbar_buttons { + .o-flex-flow(row, wrap); + + > .btn { + margin: 2px 3px 2px 0; + } + } > .o_statusbar_status { + .o-flex-flow(row-reverse, wrap-reverse); + .o-align-self(stretch); + .o-align-items(stretch); + overflow-x: hidden; // to prevent horizontal scroll due to last arrow + > .o_arrow_button { min-height: @odoo-statusbar-height; font-size: 11px; @@ -152,6 +231,7 @@ } } } + .o-status-more { .o-position-absolute(100%, 0); min-width: 100px; @@ -161,6 +241,26 @@ } } } + + // Touch device mode + > .o_statusbar_buttons > .btn-group { + > .dropdown-toggle { + &:after { + .o-caret-down(); + margin-left: @odoo-form-spacing-unit; + } + } + + > .dropdown-menu { + padding: 5px 0 2px 0; + min-width: 100px; + + > li > .btn { + min-width: 100%; + margin-bottom: 3px; + } + } + } } // Button box @@ -177,6 +277,12 @@ // Title .oe_title { + > h1, > h2, > h3 { + width: 100%; // Needed because inline-block when is a hx.o_row + margin-top: 0; + margin-bottom: 0; + line-height: inherit; + } .o_priority > .o_priority_star { font-size: inherit; } @@ -184,25 +290,62 @@ // Groups .o_group { - &.o_label_nowrap { - .o_form_label { - white-space: nowrap; + display: inline-block; + width: 100%; + margin: 10px 0; + + // o_group contains nested groups + .o-generate-groups(@odoo-form-group-cols); + .o-generate-groups(@n, @i: 1) when (@i =< @n) { + .o_group_col_@{i} { + display: inline-block; + width: floor(100% / 12 * @i); + vertical-align: top; + } + .o-generate-groups(@n, @i + 1); + } + + &.o_inner_group { + display: inline-table; + + > tbody > tr > td { + &.o_td_label { + width: 0%; + padding: 0 15px 0 0; + min-width: 150px; + } + vertical-align: top; + + span, .o_field_boolean, .oe_avatar, .o_form_uri { + &.o_field_widget { + width: auto; + } + } } } .o_form_label { font-weight: normal; } + + .o_field_widget { + width: 100%; + + > .btn { + .o-flex(0, 0, auto); + padding: 0 10px; + } + } + + &.o_label_nowrap .o_form_label { + white-space: nowrap; + } + .o_td_label .o_form_label { font-weight: bold; margin-right: 0px; } } - &.oe_form_configuration { - .o_group .o_form_label { - white-space: nowrap; - } - } // Separators .o_horizontal_separator { @@ -213,78 +356,33 @@ } } - // Labels - .o_form_label { - font-size: @font-size-base; // The label muse have the same size whatever their position - line-height: @line-height-base; - margin-right: @odoo-form-spacing-unit; - &.o_form_invalid { - color: @brand-danger; - } - } - - // ace editor RO - .oe_form_field_text .oe_form_text_content { - white-space: pre-wrap; - } - - // Tags - .o_form_field_many2manytags { - .badge { - cursor: pointer; - color: white; - font-size: 12px; - border: 0; - - > ul { - @colored-tag-width: 45px; - width: 5*@colored-tag-width + 3px; - > li { - float: left; - color: black; - > span { - border-radius: 6px; - width: @colored-tag-width; - height: 30px; - display: inline-block; - border: 2px solid white; - cursor: pointer; - padding: 0; - - &:hover { - opacity: 0.8; - } - } - } - > li:last-child { - margin-top: 7px; - cursor: auto; - } - } - } - } + // Notebooks + .o_notebook { + clear: both; // For the notebook not to have alongside floating elements + margin-top: @odoo-form-spacing-unit * 2; - .o_form_invalid { - &.o_form_input, .o_form_input, &.o_form_textarea, .o_form_textarea { - border-color: @brand-danger!important; // enterprise o_form_required rule overrides this without !important + .nav-tabs > .tab-pane { + min-height: 100px; } } - // Boolean - .o_form_field_boolean { + // Labels + .o_form_label { margin: 0 @odoo-form-spacing-unit 0 0; + font-size: @font-size-base; // The label muse have the same size whatever their position + line-height: @line-height-base; } - // Numbers - .o_form_field_number { - white-space: nowrap; + // Form fields + .o_field_widget { + margin-bottom: @odoo-form-spacing-unit; } - - // Radio buttons - .o_form_field_radio .o_form_radio { - outline: none; + .o_field_widget, .btn { + .o_field_widget { + margin-bottom: 0px; + } } - + // Translate icon .o_field_translate { padding: 0; @@ -299,160 +397,32 @@ display: inline-block; } } - .o_form_field.o_form_invisible + .o_field_translate { + .o_field_widget.o_invisible_modifier + .o_field_translate { display: none; } - // Dropdowns input (many2one, ...) - .o_form_input_dropdown { - .o-flex(1, 0, auto); - position: relative; - - > input { - padding-right: 15px; - cursor: pointer; - } - - .o_dropdown_button { - pointer-events: none; - &:after { - .o-caret-down; - } + // Text field with oe_inline class + .o_field_text.oe_inline { + width: 100%!important; + @media (min-width: @screen-xs-min) { + width: 45%!important; } } - // Many2many tags - .badge .o_delete { - cursor: pointer; - } - - // Image - .o_form_field_image { - position: relative; - - .o_form_image_controls { - .o-position-absolute(0, 0); + // One2Many, Many2Many outside of group + .o_field_widget { + &.o_view_manager_content, &.o_field_one2many, &.o_field_many2many { width: 100%; - - color: white; - background-color: @odoo-brand-optional; - opacity: 0; - transition: opacity ease 400ms; - - > .fa { - margin: 5px; - cursor: pointer; - } - } - @media (max-width: @screen-xs-min) { - .o_form_image_controls{ - position: initial; - opacity: 1; - > .fa{ - width: 50%; - padding: 6px; - margin: 0px; - text-align: center; - &.o_select_file_button{ - background: @odoo-brand-optional; - } - &.o_clear_file_button{ - background: @brand-danger; - } - } - } - } - - &:hover .o_form_image_controls { - opacity: 0.8; - } - } - - // Input loading/file - .o_form_binary_progress, .o_hidden_input_file .o_form_input_file { - display: none; - } - - // Timezone widget warning - .o_tz_warning { - color: @brand-danger; - cursor: help; - position: absolute; - margin-left: -40px; - margin-top: 5px; - } - - // One2Many Kanban views - .o_form_field .o_kanban_view.o_kanban_ungrouped { - padding: 0; - .o_kanban_record { - box-shadow: none; - } - } - - // One2Many List views - .o_form_field .o_list_view { - margin-bottom: 10px; - - > tfoot > tr > td { - padding: 3px; - color: @odoo-main-text-color; - } - } - &.o_form_readonly .o_form_field .o_list_view .o_row_handle { - display: none; // Hide the handler in non-edit mode - } - - // Percent pie field - .o_form_field_percent_pie { - .o_pie { - position: relative; - border-radius: 100%; - overflow: hidden; - background-color: @odoo-brand-optional; - - &:after { // Outside pie border to go over border-radius irregularities - content: " "; - .o-position-absolute(0, 0); + > div { width: 100%; - height: 100%; - border-radius: 100%; - } - - .o_mask { - .o-position-absolute(0, 0); - .o-transform-origin(0); - width: 50%; - height: 100%; - background-color: @odoo-view-background-color; - &.o_full { - background-color: inherit; - } - } - - .o_pie_value { - .o-flex-display(); - .o-justify-content(center); - .o-align-items(center); - - border-radius: 100%; - - font-weight: 700; - color: @odoo-brand-primary; } } } - // Attachments - .oe_attachment { - display: inline-block; - border: 1px solid @odoo-brand-lightsecondary; - margin: 0 @odoo-form-spacing-unit @odoo-form-spacing-unit 0; - padding: @odoo-form-spacing-unit; - } - // Specific style classes .o_group.o_inner_group.oe_subtotal_footer { + .oe_right; + > tbody > tr > td { padding: 0; @@ -470,7 +440,7 @@ } } - .o_form_field { + .o_field_widget { text-align: right; width: 100%; } @@ -518,7 +488,7 @@ margin-right: 0; } } - > span.o_form_field { + > span.o_field_widget { width: auto; } } @@ -556,12 +526,55 @@ } } - // Notebooks - .o_notebook { - .nav-tabs { - > .tab-pane { - min-height: 100px; - } + // Boolean + .o_field_boolean { + margin: 0 @odoo-form-spacing-unit 0 0; + } + + // Timezone widget warning + .o_tz_warning { + color: @brand-danger; + cursor: help; + position: absolute; + margin-left: -40px; + margin-top: 5px; + } + + // One2Many Kanban views + .o_field_widget .o_kanban_view.o_kanban_ungrouped { + padding: 0; + .o_kanban_record { + box-shadow: none; + } + } + + // One2Many List views + .o_field_widget .o_list_view { + margin-bottom: 10px; + + > tfoot > tr > td { + padding: 3px; + color: @odoo-main-text-color; + } + } + &.o_form_readonly .o_field_widget .o_list_view .o_row_handle { + display: none; // Hide the handler in non-edit mode + } + + // Attachments + .oe_attachment { + display: inline-block; + border: 1px solid @odoo-brand-lightsecondary; + margin: 0 @odoo-form-spacing-unit @odoo-form-spacing-unit 0; + padding: @odoo-form-spacing-unit; + } + + &.oe_form_configuration { + .o_group .o_form_label { + white-space: nowrap; + } + h2 { + margin-top: 32px !important; } } } @@ -569,16 +582,30 @@ // Overriden style when form view in modal .modal .modal-dialog { .o_form_view { - .o_form_sheet { - box-shadow: none; + .o_form_sheet_bg { + padding: 0; + + > .o_form_sheet { + box-shadow: none; + width: 100%; + margin: 0 auto; + max-width: none; + } + } + .oe_chatter { + display: none; + } + } + &:not(.modal-lg) .o_form_view { + .o_group { width: 100%; - margin: 0 auto; - max-width: none; } } +} - .o_form_invisible { - display: none!important; +@media print { + .oe_button_box, .o_form_statusbar { + display: none !important; } } @@ -619,10 +646,10 @@ label.o_light_label, .o_light_label label { margin-left: 30px; border-left: 1px solid #bbbbbb; padding-left: 10px; - .o_form_input_dropdown > .o_form_input { + .o_input_dropdown > .o_input { width: 100%; } - .o_form_field { + .o_field_widget { width: 50%; } button.btn-link { @@ -631,7 +658,3 @@ label.o_light_label, .o_light_label label { } } } - -.oe_form_configuration h2 { - margin-top: 32px !important; -} diff --git a/addons/web/static/src/less/form_view_extra.less b/addons/web/static/src/less/form_view_extra.less index 710b668c053..6e48c173c6e 100644 --- a/addons/web/static/src/less/form_view_extra.less +++ b/addons/web/static/src/less/form_view_extra.less @@ -1,10 +1,30 @@ +@sheet-max-width: 860px; +@sheet-min-width: 650px; +@sheet-padding: 16px; + .o_form_view { .o_form_sheet_bg { - background: url(/web/static/src/img/form_sheetbg.png); + position: relative; + padding: @sheet-padding 0; border-bottom: 1px solid #ddd; + background: url(/web/static/src/img/form_sheetbg.png); + .o_form_sheet { + min-width: @sheet-min-width; + max-width: @sheet-max-width; + min-height: 330px; + margin: 0 auto; + padding: 16px; border: 1px solid #c8c8d3; box-shadow: 0 4px 20px rgba(0,0,0,0.15); + background: white; + + .ui-tabs { + margin: 0 -16px; + } + .oe_notebook_page { + padding: 0 16px; + } } } @@ -16,26 +36,59 @@ .btn-default; } } - &.o_form_nosheet > header { - margin: -16px -16px 0 -16px; + &.o_form_nosheet { + padding: 16px; + &.oe_form_nomargin { + margin: 0; + } + > header { + margin: -16px -16px 0 -16px; + } } // Button box .oe_button_box { + width: 400px; + text-align: right; + float: right; + + &, & + .oe_avatar { + + .oe_title { + width: 400px; + } + } + .oe_stat_button { + text-align: left; + width: 132px !important; + height: 40px; + margin: 0px -1px -1px 0px; + padding: 0; border-radius: 0; border-color: #ccc; background: white; outline: none; + &:hover { background-color: #e6e6e6; } + .o_button_icon { + display: inline-block; + width: 37px; + padding: 0px 3px; + text-align: center; + vertical-align: middle; color: #7C7BAD; font-size: 24px; } - .o_stat_info { // contains the value and text + // Some buttons only display text and directly use the WidgetButton template instead of StatInfo + .o_stat_info, > span { // contains the value and text + display: inline-block; + max-width: 70%; + line-height: 1.2; + .o_stat_value { .o-text-overflow(block); font-weight: 700; @@ -50,19 +103,34 @@ } } } - - // Some buttons only display text and directly use the WidgetButton template instead of StatInfo > span { font-size: small; white-space: normal; // text on several lines if needed } + + > div { + text-align: left; + padding: 0; + line-height: 120%; + vertical-align: middle; + } } } // Avatar - .oe_avatar > img { - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); - border: none; + .oe_avatar { + float: left; + > img { + max-height: 90px; + max-width: 90px; + margin-bottom: 10px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); + border: none; + } + + .oe_title { + padding-left: 95px; + margin-left: 5px; + } } // Groups @@ -70,31 +138,15 @@ .o_td_label { border-right: 1px solid #ddd; } - } - - // All required form fields - .o_form_required { - &.o_form_input, .o_form_input, &.o_form_textarea, .o_form_textarea { - background-color: #D2D2FF; + .o_td_label + td { + padding: 2px 36px 2px 8px; } - } - - .o_form_field.o_form_field_many2one .o_external_button { - padding: 0; - margin-left: 2px; - font-size: 19px; - color: #7C7BAD; - border: none; - &:hover { - background-color: transparent; + .o_field_widget.o_text_overflow { + width: 1px!important; // hack to make the table layout believe it is a small element (so that the table does not grow too much) ... + min-width: 100%; // ... but in fact it takes the whole table space } } - // Dropdowns input carret - .o_form_input_dropdown .o_dropdown_button { - .o-position-absolute(2px, 4px); - } - // Separators .o_horizontal_separator { color: @odoo-brand-optional; @@ -106,30 +158,6 @@ margin-left: -15px; } - // Percent pie field - .o_form_field_percent_pie { - @pie-dimension: 34px; - @pie-ring-width: 4px; - - .o_pie { - width: @pie-dimension; - height: @pie-dimension; - margin-left: 5px; - - &:after { // Outside pie border to go over border-radius irregularities - border: 1px solid @odoo-brand-primary; - } - - .o_pie_value { - .o-position-absolute(@pie-ring-width, @pie-ring-width); - width: @pie-dimension - 2 * @pie-ring-width; - height: @pie-dimension - 2 * @pie-ring-width; - border: 1px solid white; - background-color: white; - } - } - } - // Specific style classes .o_group.o_inner_group.oe_subtotal_footer { .oe_subtotal_footer_separator { @@ -139,6 +167,15 @@ border-right: none; } } + + // Chatter + .oe_chatter { + display: block; + min-width: @sheet-min-width + 2* @sheet-padding; + max-width: @sheet-max-width + 2* @sheet-padding; + margin: 0 auto; + padding: 16px 16px 48px; + } } // Overriden style when form view in modal diff --git a/addons/web/static/src/less/form_view_layout.less b/addons/web/static/src/less/form_view_layout.less deleted file mode 100644 index 1f3cb374036..00000000000 --- a/addons/web/static/src/less/form_view_layout.less +++ /dev/null @@ -1,373 +0,0 @@ -.o_form_view { - .oe_inline { - width: auto!important; - @media (min-width: @screen-xs-min) { - &.o_inner_group { - width: 1px!important; - } - } - } - .oe_left { - .oe_inline; - float: left!important; - } - .oe_right { - .oe_inline; - float: right!important; - } - - @media (min-width: @screen-xs-min) { - .o_row { - &, &.o_form_field { // Some field may want to use o_row as root and these rules must prevalue - .o-flex-display(); - width: auto!important; - } - - .o-align-items(baseline); - min-width: 50px; - margin: 0 -@odoo-form-spacing-unit/2; - - > div, > span, > button, > label, > a, > input { // > * did not add a level of priority to the rule - .o-flex(0, 0, auto); - width: auto!important; - margin-right: @odoo-form-spacing-unit/2; - margin-left: @odoo-form-spacing-unit/2; - } - - > .o_row { - margin: 0; - } - > .btn { - padding-top: 0; - padding-bottom: 0; - } - > .o_form_field_boolean { - .o-align-self(center); - } - } - - .o_row .o_form_field_many2one, .o_form_field_many2one.oe_inline { - &.o_with_button:not(:last-child) { // If invisible element as last child, this line has no effect but that's not very important - margin-right: (35px + (@odoo-form-spacing-unit/2)); - } - } - } - - .o_row > div > .o_form_field { - width: 100%; - } - - // Readonly specific rules - &.o_form_readonly { - .o_row { - display: inline-block; - > div { - display: inline-block; - } - } - } - - // Editable specific rules - &.o_form_editable { - @media (min-width: @screen-xs-min) { - .o_row { - > .o_form_field, > div { - .o-flex(1, 1, auto); - width: 0!important; // 3rd flex argument does not work with input (must be auto and real width 0) - - &.o_form_field_boolean, &.o_priority { - .o-flex(0, 0, auto); - width: auto!important; - } - } - } - } - - .oe_title { - max-width: @container-sm - (2 * @odoo-horizontal-padding); - } - } - - // Header containing status/workflow buttons - .o_form_statusbar { - .o-flex(0, 0, auto); - .o-flex-display(); - .o-justify-content(space-between); - - padding-left: @odoo-horizontal-padding; - - > .o_statusbar_buttons, > .o_statusbar_status { - .o-flex-display(); - .o-align-items(center); - .o-align-content(space-around); - } - - > .o_form_field { - .o-align-self(center); - margin-bottom: 0px; - } - - > .o_statusbar_buttons { - .o-flex-flow(row, wrap); - - > .btn { - margin: 2px 3px 2px 0; - } - } - - > .o_statusbar_status { - .o-flex-flow(row-reverse, wrap-reverse); - .o-align-self(stretch); - .o-align-items(stretch); - overflow-x: hidden; // to prevent horizontal scroll due to last arrow - } - - // Touch device mode - > .o_statusbar_buttons > .btn-group { - > .dropdown-toggle { - &:after { - .o-caret-down(); - margin-left: @odoo-form-spacing-unit; - } - } - - > .dropdown-menu { - padding: 5px 0 2px 0; - min-width: 100px; - - > li > .btn { - min-width: 100%; - margin-bottom: 3px; - } - } - } - } - - // Title - .oe_title { - > h1, > h2, > h3 { - width: 100%; // Needed because inline-block when is a hx.o_row - margin-top: 0; - margin-bottom: 0; - line-height: inherit; - } - } - - // Groups - .o_group { - display: inline-block; - width: 100%; - margin: 10px 0; - - // o_group contains nested groups - .o-generate-groups(@odoo-form-group-cols); - .o-generate-groups(@n, @i: 1) when (@i =< @n) { - .o_group_col_@{i} { - display: inline-block; - width: floor(100% / 12 * @i); - vertical-align: top; - } - .o-generate-groups(@n, @i + 1); - } - - &.o_inner_group { - display: inline-table; - - > tbody > tr > td { - &.o_td_label { - width: 0%; - padding: 0 15px 0 0; - min-width: 150px; - } - vertical-align: top; - - span, .o_form_field_boolean, .oe_avatar, .o_form_uri { - &.o_form_field { - width: auto; - } - } - } - } - - .o_form_field { - width: 100%; - - > .btn { - .o-flex(0, 0, auto); - padding: 0 10px; - } - } - } - - // Notebooks - .o_notebook { - clear: both; // For the notebook not to have alongside floating elements - margin-top: @odoo-form-spacing-unit * 2; - } - - // Labels - .o_form_label { - margin: 0; - } - - // Form fields - .o_form_field { - display: inline-block; - margin-bottom: @odoo-form-spacing-unit; - } - - // Block fields - .note-editor, .oe_form_field_html, .oe_form_field_html_text, .oe_form_field_text, .o_view_manager_content, .o_form_field_domain { - display: block; - } - - // Flex fields - .o_form_field_many2one, .o_form_field_radio, .o_form_field_many2manytags, .o_form_field_percent_pie, .o_form_field_monetary, .o_form_field_binary_file { - @media (min-width: @screen-sm-min) { - .o-inline-flex-display(); - } - > span, > button { - .o-flex(0, 0, auto); - } - } - - .o_form_field, .btn { - .o_form_field { - margin-bottom: 0px; - } - } - - // Input in field - .o_form_field { - .o_form_input_dropdown { - width: 100%; - } - .o_form_input { - display: inline-block; - } - } - - // Textarea - .o_form_textarea { - white-space: pre-wrap; - width: 100%; - &.oe_inline { - width: 100%!important; - @media (min-width: @screen-xs-min) { - width: 45%!important; - } - } - } - - // Radio buttons - .o_form_field_radio { - .o_radio_item { - .o-flex(0, 0, auto); - .o-flex-display(); - .o-align-items(center); - - > input { - .o-flex(0, 0, auto); - margin: 0 @odoo-form-spacing-unit 0 0; - } - > label { - margin: 0; - } - } - - &.o_horizontal { - .o_radio_item { - margin-right: @odoo-form-spacing-unit * 2; - } - } - - &.o_vertical { - .o-flex-flow(column, nowrap); - .o_radio_item { - margin-bottom: @odoo-form-spacing-unit; - } - } - } - - // One2Many, Many2Many outside of group - .o_form_field { - &.o_view_manager_content, &.o_form_field_one2many, &.o_form_field_many2many { - width: 100%; - > div { - width: 100%; - } - } - } - - // Many2many tags - .o_form_field_many2manytags { - .o-flex-flow(row, wrap); - .o-align-items(baseline); - .badge { - .o-flex(0, 0, auto); - > .o_badge_text { - .o-text-overflow(inline-block); - max-width: 200px; - } - } - } - - // Percent pie - .o_form_field_percent_pie { - .o-align-items(center); - > .o_pie { - margin-right: 10px; - } - } - - // Specific style classes - .o_group.o_inner_group.oe_subtotal_footer { - .oe_right; - } - - //ace - .o_ace_view_editor { - width: 100%; - .ace-view-editor { - height: 300px; - padding: 0 1em; - } - } - - .o_form_field_domain { - > .o_form_field_domain_panel { - margin-top: 8px; - } - &.o_inline_mode.o_edit_mode { - position: relative; - - > .o_form_field_domain_panel { - .o-position-absolute(0, 0); - margin-top: 0; - } - } - } -} - -// Overriden style when form view in modal -.modal .modal-dialog { - .o_form_view { - .o_form_sheet_bg { - padding: 0; - } - .oe_chatter { - display: none; - } - } - &:not(.modal-lg) .o_form_view { - .o_group { - width: 100%; - } - } -} - -@media print { - .oe_button_box { - display: none !important; - } -} diff --git a/addons/web/static/src/less/form_view_layout_extra.less b/addons/web/static/src/less/form_view_layout_extra.less deleted file mode 100644 index 51c1c3f731e..00000000000 --- a/addons/web/static/src/less/form_view_layout_extra.less +++ /dev/null @@ -1,109 +0,0 @@ -@sheet-max-width: 860px; -@sheet-min-width: 650px; -@sheet-padding: 16px; - -.o_form_view { - &.o_form_nosheet { - padding: 16px; - &.oe_form_nomargin { - margin: 0; - } - } - .o_form_sheet_bg { - position: relative; - padding: @sheet-padding 0; - .o_form_sheet { - min-width: @sheet-min-width; - max-width: @sheet-max-width; - min-height: 330px; - background: white; - padding: 16px; - margin: 0 auto; - .ui-tabs { - margin: 0 -16px; - } - .oe_notebook_page { - padding: 0 16px; - } - } - } - - // Button box - .oe_button_box { - width: 400px; - text-align: right; - float: right; - .oe_stat_button { - text-align: left; - width: 132px !important; - height: 40px; - margin: 0px -1px -1px 0px; - padding: 0; - > div { - text-align: left; - padding: 0; - line-height: 120%; - vertical-align: middle; - } - .o_button_icon { - display: inline-block; - width: 30%; - padding: 0px 3px; - width: 37px; - text-align: center; - vertical-align: middle; - } - - .o_stat_info { // contains the value and text - display: inline-block; - max-width: 70%; - line-height: 1.2; - } - - // Some buttons only display text and directly use the WidgetButton template instead of StatInfo - > span { - .o_stat_info; // layout - } - } - - &, & + .oe_avatar { - + .oe_title { - width: 400px; - } - } - } - - // Groups - .o_group { - .o_td_label + td { - padding: 2px 36px 2px 8px; - } - .o_form_field.o_text_overflow { - width: 1px!important; // hack to make the table layout believe it is a small element (so that the table does not grow too much) ... - min-width: 100%; // ... but in fact it takes the whole table space - } - } - - // Avatar - .oe_avatar { - float: left; - > img { - max-height: 90px; - max-width: 90px; - margin-bottom: 10px; - } - + .oe_title { - padding-left: 95px; - margin-left: 5px; - } - } - - // Chatter - .oe_chatter { - display: block; - min-width: @sheet-min-width + 2* @sheet-padding; - max-width: @sheet-max-width + 2* @sheet-padding; - margin: 0 auto; - padding: 16px 16px 48px; - } -} diff --git a/addons/web/static/src/less/kanban_view.less b/addons/web/static/src/less/kanban_view.less index 9b2f914d3b4..d1e39c8b18e 100644 --- a/addons/web/static/src/less/kanban_view.less +++ b/addons/web/static/src/less/kanban_view.less @@ -123,7 +123,7 @@ } } } - .o_form_field_many2manytags { + .o_field_many2manytags { display: block; } .oe_kanban_text_red { @@ -552,3 +552,8 @@ color: #639B89; } } + +// Introduced with new views (TODO check) +.o_kanban { + height: 100%; // required for grouped kanban views +} diff --git a/addons/web/static/src/less/list_view.less b/addons/web/static/src/less/list_view.less index bad4e370961..8fad7a04527 100644 --- a/addons/web/static/src/less/list_view.less +++ b/addons/web/static/src/less/list_view.less @@ -1,5 +1,7 @@ @odoo-list-group-header-color: lighten(@odoo-brand-lightsecondary, 10%); + .o_list_view { + position: relative; cursor: pointer; background-color: @odoo-view-background-color; margin-bottom: 0px; @@ -12,7 +14,6 @@ thead { color: @odoo-main-text-color; - background-color: #eee; border-bottom: 1px solid #cacaca; > tr > th { border-left: 1px solid #dfdfdf; @@ -46,23 +47,8 @@ } } - .o_list_record_selector { + .o_list_record_selector, .o_list_record_delete, .o_handle_cell { width: 1px; // to prevent the column to expand - > input { - margin-left: 3px; - .hidden-xs(); - } - } - - .o_list_record_delete { - width: 13px; - } - - .o_handle_cell { - width: 1px; // to prevent the column to expand - .o_row_handle { - cursor: ns-resize; - } } // Decoration of the row @@ -80,8 +66,6 @@ tbody > tr.o_group_header { height: 31px; - .o-vertical-gradient(#fcfcfc, #dedede); - .o_group_name { white-space: nowrap; } @@ -106,108 +90,77 @@ border-top: none; // Override bootstrap for grouped list views } - .o_list_number { - text-align: right; - white-space: nowrap; - } - .o_list_text { - white-space: pre-wrap; - } -} - -.o_list_editable { - position: relative; - - .o_temp_visible { - opacity: 0; - display: block!important; - - &.o_form_invisible { - display: block!important; + // Values styling + .o_data_cell { + &.o_list_number, &.o_field_integer, &.o_field_float, &.o_field_monetary { + text-align: right; + white-space: nowrap; + } + &.o_list_text, &.o_field_text { + white-space: pre-wrap; } } - .o_list_view { - .o_row_edition > td { - visibility: hidden; // Hide row's content during edition - &.o_list_record_selector, &.o_list_record_delete, &.o_list_button { - visibility: visible; - } - - &.o_list_record_delete { - opacity: 0.5; - pointer-events: none; - } + //-------------------------------------------------------------------------- + // Edition + //-------------------------------------------------------------------------- + .o_data_row.o_selected_row > .o_data_cell:not(.o_readonly_modifier) { + position: relative; + padding: 0; - &.o_readonly { - visibility: visible; - color: transparent; + // Field widgets override + > .o_field_widget { + .o-position-absolute(0, 0, auto, 0); + min-height: 100%; - > .o_checkbox { - visibility: hidden; - } + &:not(.o_field_text) { + white-space: nowrap; } - } - } - .o_form_view.o_list_editable_form { - padding: 0; - > .o_form_field { - padding: 0; - position: absolute; - white-space: nowrap; - &.o_form_textarea { - white-space: pre-wrap; - } - .o_form_field, .badge { // Many2Many tags + .o_field_widget, .badge { // Many2Many tags display: block; float: left; white-space: normal; max-width: 100%; // Fix a chrome bug where badge would not break on multiple lines } - - &.o_readonly:not(.o_checkbox) { - background-color: transparent; - padding: 5px; - } } > .o_field_translate { position: absolute; width: 16px; // to have some space on the right } - .o_form_input_dropdown { - height: 100%; - } - .o_form_input { - height: 100%; - padding-left: 5px; - padding-right: 5px; + .o_input { + padding: 4px; // bootstrap cell - 1px of border + background-color: white; + + .o_input { + padding: 0!important; + } } - .o_form_input, .o_form_textarea, .o_form_field_many2manytags, .o_form_field_monetary { - border-style: solid; + .o_input_dropdown { + min-height: 100%; } - .o_form_field_monetary .o_form_input { + .o_field_monetary input { width: 0; } .o_checkbox { padding: 7px 0 0 5px; background: transparent; } - .o_form_textarea { + .o_field_widget { min-width: 0; } - .o_with_button .o_form_input_dropdown { + .o_with_button .o_input_dropdown { width: 1%; // Hack so that the sibling button is not overlapped } - .o_form_input_dropdown, .o_datepicker { - > .o_form_input { + .o_input_dropdown, .o_datepicker { + > .o_input { padding-right: 15px; // To prevent caret overlapping } > .o_dropdown_button, .o_datepicker_button { .o-position-absolute(20%, 5px); } } - .o_form_field > .o_external_button { + .o_field_widget > .o_external_button { padding: 0; background-color: inherit; margin-left: 3px; @@ -215,24 +168,15 @@ .o_row_handle { visibility: hidden; // Hide sequence when editing } - .o_form_field_boolean { + .o_field_boolean { width: auto!important; // Override the width computed in JS (needed for Chrome) } - .o_form_field_number { + .o_field_number { text-align: right; } } } -// Workaround a bug in safari mobile where the inputs are not displayed correctly. -.modal { - .o_list_editable { - .o_form_view.o_list_editable_form { - -webkit-overflow-scrolling: auto; - } - } -} - // Buttons in ControlPanel .o_list_buttons { .o_list_button_save, .o_list_button_discard { diff --git a/addons/web/static/src/less/list_view_extra.less b/addons/web/static/src/less/list_view_extra.less new file mode 100644 index 00000000000..9a9413c0dd7 --- /dev/null +++ b/addons/web/static/src/less/list_view_extra.less @@ -0,0 +1,10 @@ + +.o_list_view { + thead { + background-color: #eee; + } + + tbody > tr.o_group_header { + .o-vertical-gradient(#fcfcfc, #dedede); + } +} diff --git a/addons/web/static/src/less/model_field_selector.less b/addons/web/static/src/less/model_field_selector.less index 095e8b699f9..124c15cb8e5 100644 --- a/addons/web/static/src/less/model_field_selector.less +++ b/addons/web/static/src/less/model_field_selector.less @@ -28,8 +28,6 @@ } &.o_edit_mode { - .o-input(); - > .o_field_selector_controls::after { .o-caret-down(); } diff --git a/addons/web/static/src/less/navbar.less b/addons/web/static/src/less/navbar.less index 5f3aff0b98f..4e709ed7f9b 100644 --- a/addons/web/static/src/less/navbar.less +++ b/addons/web/static/src/less/navbar.less @@ -1,10 +1,10 @@ .o_main_navbar { + position: relative; height: @odoo-navbar-height; border: 1px solid @odoo-navbar-inverse-link-hover-bg; background-color: @odoo-brand-primary; color: white; - .box-shadow(0px 0px 8px @odoo-main-text-color); > a, > button { float: left; @@ -29,6 +29,24 @@ } } + > .o_menu_brand { + display: block; + float: left; + margin-right: 35px; + .user-select(none); + color: white; + font-size: 22px; + font-weight: 500; + line-height: @odoo-navbar-height - 2; + + @media (max-width: @screen-xs-max) { + float: none; + margin: 0; + border-bottom: 1px solid @odoo-navbar-inverse-link-hover-bg; + color: transparent; + } + } + > .o_menu_toggle { margin-right: 5px; } @@ -60,6 +78,37 @@ outline: none; } } + + &.o_extra_menu_items { + > a { + width: @odoo-navbar-height - 2; + text-align: center; + } + &.open > ul { + padding: 0; + + > li { + > a { + background-color: @odoo-brand-primary; + color: white; + border-bottom: 1px solid @odoo-brand-lightsecondary; + + &.dropdown-toggle { + background-color: lighten(@odoo-brand-primary, 15%); + pointer-events: none; // hack to prevent clicking on it because dropdown always opened + } + } + > ul { // remove dropdown-menu default style as it is nested in another one + position: static; + float: none; + display: block; + border: none; + box-shadow: none; + max-height: none; + } + } + } + } } &.o_menu_systray { @@ -71,10 +120,6 @@ } } - .o_menu_brand { - display: none; - } - .open .dropdown-menu { max-height: 90vh; // the dropdown should not overstep the viewport overflow: auto; @@ -89,6 +134,10 @@ .o-menu-indentation(3); } + .oe_topbar_avatar { + height: 15px; + } + @media (max-width: @screen-xs-max) { .o-transition(height, 200ms, linear); diff --git a/addons/web/static/src/less/new_views.less b/addons/web/static/src/less/new_views.less deleted file mode 100644 index f8c0ca2e7b6..00000000000 --- a/addons/web/static/src/less/new_views.less +++ /dev/null @@ -1,83 +0,0 @@ -.o_kanban { - height: 100%; // required for grouped kanban views -} - -.o_list_view { - tr.o_selected_row { - outline: 1px solid lightgray; - - > td:not(.o_readonly):not(.o_list_button) { - position: relative; - background-color: white; - - > .o_field_widget, > .o_form_field_many2one { - .o-position-absolute(0, 0, 0, 0); - } - - .o_form_field_many2one .o_form_input_dropdown { - .o-flex(1, 1, auto); - - .o_form_input { - height: 100%; - } - - .o_dropdown_button { - display: none; - } - } - - .o_form_field_many2manytags { - .o_form_field_many2one { - height: 100%; - display: inline-block; - } - } - - .o_field_boolean { - .o-flex-display(); - .o-align-items(center); - } - } - } - - td.o_field_dirty { - outline: 1px solid orange; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Rules on fields moved from form_view(_layout).less (community or enterprise) -// so that they also apply outside a form_view - -// Many2One -.o_form_field_many2one { - .o-inline-flex-display(); - > span, > button { - .o-flex(0, 0, auto); - } -} -// Many2ManyTags -.o_form_field_many2manytags .badge { - cursor: pointer; - color: white; - font-size: 12px; - border: 0; -} -// Dropdowns input (many2one, ...) -.o_form_input_dropdown { - .o-flex(1, 0, auto); - position: relative; - - > input { - padding-right: 15px; - cursor: pointer; - } - - .o_dropdown_button { - pointer-events: none; - &:after { - .o-caret-down; - } - .o-position-absolute(0, 0); // ENTERPRISE ONLY - } -} diff --git a/addons/web/static/src/less/search_view_extra.less b/addons/web/static/src/less/search_view_extra.less index 0ef7b8dd1dd..9c263976e4d 100644 --- a/addons/web/static/src/less/search_view_extra.less +++ b/addons/web/static/src/less/search_view_extra.less @@ -11,7 +11,7 @@ .o_searchview_facet_label { background-color: @gray-light; } - + .o_facet_remove { color: @gray-light; &:hover { @@ -40,5 +40,4 @@ input[type="text"], select { .form-control(); } - } diff --git a/addons/web/static/src/less/switch_company_menu.less b/addons/web/static/src/less/switch_company_menu.less deleted file mode 100644 index 08774e24d49..00000000000 --- a/addons/web/static/src/less/switch_company_menu.less +++ /dev/null @@ -1,6 +0,0 @@ -.o_company { - margin-right:23px; -} -.o_current_company { - margin-right:10px; -}
\ No newline at end of file diff --git a/addons/web/static/src/less/tree_view.less b/addons/web/static/src/less/tree_view.less deleted file mode 100644 index 66db28f58a8..00000000000 --- a/addons/web/static/src/less/tree_view.less +++ /dev/null @@ -1,50 +0,0 @@ -.o_treeview_table { - width: 100%; - background-color: white; - border-collapse: collapse; - - thead { - color: @odoo-main-text-color; - background-color: @odoo-brand-lightsecondary; - > tr > th { - padding: 10px; - } - } - - tbody { - > tr { - border: 1px solid @odoo-brand-lightsecondary; - &:hover { - background-color: lighten(@odoo-brand-lightsecondary, 15%); - } - > td { - border: 1px solid @odoo-brand-lightsecondary; - cursor: pointer; - height: 40px; - padding: 0 4px; - &.oe_number { - text-align: right; - } - } - } - .treeview-tr, .treeview-td { - &.o_treeview_first > span { - padding-left: 16px; - } - } - .treeview-tr.o_treeview_first { - position: relative; - &:before { - position: absolute; - top: 13px; - .o-caret-right(6px); - } - } - .o_open .treeview-tr.o_treeview_first { - &:before { - top: 16px; - .o-caret-down(6px); - } - } - } -}
\ No newline at end of file diff --git a/addons/web/static/src/less/utils.less b/addons/web/static/src/less/utils.less index 8d85eb0d977..19068dd3545 100644 --- a/addons/web/static/src/less/utils.less +++ b/addons/web/static/src/less/utils.less @@ -209,9 +209,9 @@ // ------------------------------------------------------------------ // Text overflow // ------------------------------------------------------------------ -.o-text-overflow(@display: inline-block) { +.o-text-overflow(@display: inline-block, @max-width: 100%) { display: @display; - max-width: 100%; + max-width: @max-width; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; diff --git a/addons/web/static/src/less/views.less b/addons/web/static/src/less/views.less index f2f9a97ee1b..db5fe8f814c 100644 --- a/addons/web/static/src/less/views.less +++ b/addons/web/static/src/less/views.less @@ -1,87 +1,7 @@ -// -------------------------------------------------------------------------- -// This file contains rules applying on elements shared between views -// -------------------------------------------------------------------------- - -// Many2many tags -.o_form_field_many2manytags { - .o_tag_color_0 { - background-color: #4D4D4D; - } - .o_tag_color_1 { - background-color: #61BD4F; - } - .o_tag_color_2 { - background-color: #F2D600; - } - .o_tag_color_3 { - background-color: #FFAB4A; - } - .o_tag_color_4 { - background-color: #EB5A46; - } - .o_tag_color_5 { - background-color: #875A7B; - } - .o_tag_color_6 { - background-color: #0079BF; - } - .o_tag_color_7 { - background-color: #00C2E0; - } - .o_tag_color_8 { - background-color: #4CD98E; - } - .o_tag_color_9 { - background-color: #FF80CE; - } - .o_tag_color_10 { - background-color: #B6BBBF; - } -} - -// Stars -.o_priority { - display: inline-block; - padding: 0; - margin: 0; - vertical-align: middle; - > .o_priority_star { - display: inline-block; - font-size: 1.35em; - &:hover, &:focus { - text-decoration: none; - outline: none; - } - - + .o_priority_star { - padding-left: 5px; - } - - &.fa-star-o { - color: @odoo-main-color-muted; - } - &.fa-star { - color: gold; - } - } -} - -.o_status { - display: inline-block; - height: 12px; - width: 12px; - border-radius: 6px; - vertical-align: middle; - - background-color: @odoo-brand-secondary; - - &.o_status_green { - background-color: @brand-success; - } - &.o_status_red { - background-color: @brand-danger; - } -} +/** + * This file regroups the rules which apply on elements which are shared between + * all renderers. For field default rules, see the fields.less file. + */ // No content helper .oe_view_nocontent { @@ -92,15 +12,12 @@ display: inline!important; } } -// Hide view_nocontent in x2many fields -.o_form_field .oe_view_nocontent { - display: none; -} +.o_field_widget .oe_view_nocontent, .o_cannot_create .oe_view_nocontent_create { display: none; } -// Specific success color for toggle_button widget -.fa.o_toggle_button_success { - color: @brand-success; +// Invisible modifier (can be inside the view, the button area, ...) +.o_invisible_modifier { + display: none!important; } diff --git a/addons/web/static/src/less/web_calendar.less b/addons/web/static/src/less/web_calendar.less index b23b64bcfa7..ed25f8f8dd0 100644 --- a/addons/web/static/src/less/web_calendar.less +++ b/addons/web/static/src/less/web_calendar.less @@ -194,7 +194,7 @@ .o_calendar_filter { padding: 8px; border-top: 1px solid lightgray; - .o_form_field_many2one { + .o_field_many2one { width: 100%; } } diff --git a/addons/web/static/src/less/webclient_extra.less b/addons/web/static/src/less/webclient_extra.less index 43d316ec3a0..7c337352618 100644 --- a/addons/web/static/src/less/webclient_extra.less +++ b/addons/web/static/src/less/webclient_extra.less @@ -1,6 +1,6 @@ -// ------------------------------------------------------------------ +//------------------------------------------------------------------------------ // Checkboxes -// ------------------------------------------------------------------ +//------------------------------------------------------------------------------ div.o_checkbox { display: inline-block; vertical-align: sub; @@ -9,29 +9,32 @@ div.o_checkbox { } } -// ------------------------------------------------------------------ -// Inputs and selects -// ------------------------------------------------------------------ -.o-input() { +//------------------------------------------------------------------------------ +// Inputs and selects (note: put the o_input class to have the style) +//------------------------------------------------------------------------------ +[type="text"], [type="password"], [type="number"], textarea, select { + width: 100%; + display: block; + outline: none; +} +.o_input { border: 1px solid @odoo-form-lightsecondary; border-radius: @border-radius-base; padding: 2px 4px; color: #1f1f1f; -} -input[type="text"], input[type="password"], input[type="number"], textarea, select { - .o-input(); - width: 100%; - outline: none; - display: block; + .o_input { + border: none!important; + padding: 0; + } } select { background: white; } -// ------------------------------------------------------------------ +//------------------------------------------------------------------------------ // Loading -// ------------------------------------------------------------------ +//------------------------------------------------------------------------------ .o_loading { position: fixed; top: 0; @@ -45,9 +48,9 @@ select { border-bottom-left-radius: 8px; } -// ------------------------------------------------------------------ +//------------------------------------------------------------------------------ // User menu in navbar -// ------------------------------------------------------------------ +//------------------------------------------------------------------------------ #oe_main_menu_navbar .oe_user_menu_placeholder .o_user_menu .oe_topbar_name { .o-text-overflow(); max-width: 150px; diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 6ffe8fca2db..d89d11f0cd5 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -2,7 +2,9 @@ <templates id="template" xml:space="preserve"> <div t-name="EmptyComponent"/> + <div t-name="Loading" class="o_loading"/> + <t t-name="Notification"> <div t-attf-class="o_notification #{className}" t-translation="off"> <a t-if="widget.sticky" class="fa fa-times o_close" href="#"/> @@ -49,15 +51,15 @@ <table class="o_group o_inner_group o_label_nowrap"> <tr> <td class="o_td_label"><label for="old_pwd" class="o_form_label">Old Password</label></td> - <td width="100%"><input type="password" class="o_form_field o_form_input" name="old_pwd" minlength="1" autofocus="autofocus" autocomplete="current-password"/></td> + <td width="100%"><input type="password" class="o_field_widget o_input" name="old_pwd" minlength="1" autofocus="autofocus" autocomplete="current-password"/></td> </tr> <tr> <td class="o_td_label"><label for="new_password" class="o_form_label">New Password</label></td> - <td width="100%"><input type="password" class="o_form_field o_form_input" name="new_password" minlength="1" autocomplete="new-password"/></td> + <td width="100%"><input type="password" class="o_field_widget o_input" name="new_password" minlength="1" autocomplete="new-password"/></td> </tr> <tr> <td class="o_td_label"><label for="confirm_pwd" class="o_form_label">Confirm New Password</label></td> - <td width="100%"><input type="password" class="o_form_field o_form_input" name="confirm_pwd" minlength="1" autocomplete="new-password"/></td> + <td width="100%"><input type="password" class="o_field_widget o_input" name="confirm_pwd" minlength="1" autocomplete="new-password"/></td> </tr> </table> @@ -83,7 +85,6 @@ </div> </div> </t> - <t t-name="X2ManyControlPanel"> <div class="o_x2m_control_panel"> <div class="o_cp_buttons"/> @@ -108,7 +109,6 @@ <ul class="dropdown-menu o_debug_dropdown" role="menu"/> </li> </t> - <t t-name="WebClient.DebugManager.Global"> <li><a href="#" data-action="perform_js_tests">Run JS Tests</a></li> <li><a href="#" data-action="select_view">Open View</a></li> @@ -255,48 +255,6 @@ </t> </t> -<t t-name="TreeView"> - <select t-if="toolbar" style="width: 30%"/> - <table class="o_treeview_table"> - <thead> - <tr> - <th t-foreach="fields_view" t-as="field" - t-if="!field.attrs.modifiers.tree_invisible" - class="treeview-header"> - <t t-esc="field_value.attrs.string || fields[field.attrs.name].string" /> - </th> - </tr> - </thead> - <tbody> - </tbody> - </table> -</t> -<tr t-name="TreeView.rows" - t-foreach="records" t-as="record" - t-att-id="'treerow_' + record.id" - t-att-data-id="record.id" t-att-data-level="level + 1" - t-att-data-row-parent-id="row_parent_id"> - <t t-set="children" t-value="record[children_field]"/> - <t t-set="class" t-value="children and children.length ? 'treeview-tr' : 'treeview-td'"/> - <t t-set="rank" t-value="'o_treeview_first'"/> - <t t-set="style" t-value="'background-position: ' + 19*(level) + 'px; padding-left: ' + (4 + 19*(level)) + 'px;'"/> - - <td t-foreach="fields_view" t-as="field" - t-if="!field.attrs.modifiers.tree_invisible" - t-att-data-id="record.id" - t-att-style="color_for(record) + style " - t-attf-class="#{class} #{rank} #{(fields[field.attrs.name].type === 'float') or (fields[field.attrs.name].type === 'integer') or (fields[field.attrs.name].type === 'monetary')? 'oe_number' : ''}"> - - <span t-if="!field.attrs.modifiers.invisible" > - <t t-esc="render(record[field.attrs.name], fields[field.attrs.name])" /> - </span> - - <t t-set="class" t-value="'treeview-td'"/> - <t t-set="rank" t-value="''"/> - <t t-set="style" t-value="''"/> - </td> -</tr> - <div t-name="ListView" class="table-responsive"> <table class="o_list_view table table-condensed table-striped"> <t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/> @@ -332,7 +290,6 @@ </tfoot> </table> </div> - <t t-name="ListView.buttons"> <div class="o_list_buttons"> <t t-if="widget.is_action_enabled('create')"> @@ -349,60 +306,6 @@ </div> </t> -<t t-name="ListView.rows" t-foreach="records.length" t-as="index"> - <t t-call="ListView.row"> - <t t-set="record" t-value="records.at(index)"/> - </t> -</t> - -<tr t-name="ListView.row" - t-att-data-id="record.get('id')" - t-attf-style="#{(view.fonts || view.colors) ? view.style_for(record) : ''}" - t-attf-class="#{view.compute_decoration_classnames(record)}"> - <t t-set="asData" t-value="record.toForm().data"/> - <t t-foreach="columns" t-as="column"> - <td t-if="column.meta"> </td> - </t> - <td t-if="options.selectable" class="o_list_record_selector"> - <t t-set="checked" t-value="options.select_view_id == record.get('id') ? 'checked' : null"/> - <input t-if="options.radio" type="radio" name="radiogroup" t-att-checked="checked"/> - <div t-if="!options.radio" class="o_checkbox"> - <input type="checkbox" name="radiogroup" t-att-checked="checked"/><span/> - </div> - </td> - <t t-foreach="columns" t-as="column"> - <t t-set="number" t-value="column.type === 'integer' or column.type == 'float' or column.type == 'monetary'"/> - <t t-set="text" t-value="column.type === 'text'"/> - <t t-set="modifiers" t-value="column.modifiers_for(asData)"/> - <td t-if="!column.meta and column.invisible !== '1'" t-att-title="column.help" - t-attf-class="#{modifiers.readonly ? 'o_readonly' : ''} #{number ? 'o_list_number' : ''} #{text ? 'o_list_text' : ''} #{column.id === 'sequence' ? 'o_handle_cell' : ''} #{column.tag === 'button' ? 'o_list_button' : ''}" - t-att-data-field="column.id" - ><t t-raw="render_cell(record, column)"/></td> - </t> - <td t-if="options.deletable" class='o_list_record_delete'> - <span name="delete" class="fa fa-trash-o"/> - </td> -</tr> - -<button t-name="ListView.row.text_button" type="button" - t-att-title="widget.string" t-att-disabled="disabled || undefined" - t-att-class="disabled ? 'oe_list_button_disabled btn_txt oe_link' : 'btn_txt oe_link'" - ><t t-esc="widget.string"/></button> -<button t-name="ListView.row.button" type="button" - t-att-title="widget.string" t-att-disabled="disabled || undefined" - t-attf-class="o_icon_button #{disabled ? 'oe_list_button_disabled' : ''}" - ><i t-attf-class="fa #{widget.icon}" t-att-title="widget.string"/> -</button> -<t t-extend="ListView.row"> - <!-- adds back padding to row being rendered after edition, if necessary - (if not deletable add back padding), otherwise the row being added is - missing columns - --> - <t t-jquery="> :last" t-operation="after"> - <td t-if="edited and !options.deletable" class="oe-listview-padding"/> - </t> -</t> - <t t-name="FormView.buttons"> <div class="o_form_buttons_view"> <button t-if="widget.is_action_enabled('edit')" type="button" @@ -546,7 +449,6 @@ <button class="btn btn-default fa fa-pie-chart o_graph_button" title="Pie Chart" data-mode="pie"/> </div> </t> - <div t-name="GraphView.error" class="oe_view_nocontent" > <p><strong><t t-esc="title"/></strong></p> <p><t t-esc="description"/></p> @@ -555,7 +457,6 @@ <div t-name="PivotView" class="o_pivot"> <div class="o_field_selection"/> </div> - <t t-name="PivotView.buttons"> <div class="btn-group btn-group-sm" role="group"> <button class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown"> @@ -575,7 +476,6 @@ <button class="btn btn-default fa fa-download o_pivot_download" title="Download xls"/> </div> </t> - <t t-name="PivotView.FieldSelection"> <ul class="dropdown-menu o_pivot_field_menu" role="menu"> <t t-foreach="fields" t-as="field"> @@ -601,7 +501,6 @@ </t> </ul> </t> - <div t-name="PivotView.nodata" class="oe_view_nocontent" > <p><strong>No data to display.</strong></p> <p> @@ -610,24 +509,10 @@ </p> </div> - <t t-name="Widget"> Unhandled widget <t t-js="dict">console.warn('Unhandled widget', dict.widget);</t> </t> -<t t-name="FieldChar"> - <span t-if="widget.get('effective_readonly')"/> - - <input t-if="!widget.get('effective_readonly')" class="o_form_input" - t-att-barcode_events="widget.options.barcode_events" - t-att-type="widget.password ? 'password' : 'text'" - t-att-id="widget.idForLabel" - t-att-tabindex="widget.node.attrs.tabindex" - t-att-autofocus="widget.node.attrs.autofocus" - t-att-placeholder="widget.node.attrs.placeholder" - t-att-autocomplete="widget.password ? 'new-password' : widget.node.attrs.autocomplete" - t-att-maxlength="widget.field.size"/> -</t> <t t-name="FormSelection"> <div class="btn-group o_selection"> <a href="#" data-toggle="dropdown"><span class="o_status"/></a> @@ -643,29 +528,8 @@ </a> </li> </t> -<t t-name="FieldEmail" t-extend="FieldChar"> - <t t-jquery="span" t-operation="replace"> - <t t-if="widget.get('effective_readonly')"> - <a t-if="widget.clickable" class="o_form_uri o_text_overflow" href="#" target="_blank"/> - <span t-if="!widget.clickable" class="o_text_overflow"/> - </t> - </t> -</t> -<t t-name="FieldText"> - <span t-if="widget.get('effective_readonly')" class="o_form_textarea"/> - - <textarea t-if="!widget.get('effective_readonly')" - class="o_form_textarea" - rows="6" - t-att-name="widget.name" - t-att-tabindex="widget.node.attrs.tabindex" - t-att-autofocus="widget.node.attrs.autofocus" - t-att-placeholder="!widget.get('effective_readonly') ? widget.node.attrs.placeholder : ''" - t-att-maxlength="widget.field.size"/> -</t> - <t t-name="FieldDomain.content"> - <div t-if="hasModel" class="o_form_field_domain_panel"> + <div t-if="hasModel" class="o_field_domain_panel"> <i class="fa fa-arrow-right"/> <button t-if="isValid" class="btn btn-xs btn-default o_domain_show_selection_button" type="button"> @@ -673,11 +537,10 @@ </button> <span t-else="" class="text-warning"><i class="fa fa-exclamation-triangle"/> Invalid domain</span> - <button t-if="inDialogEdit" class="btn btn-xs btn-primary o_form_field_domain_dialog_button">Edit domain</button> + <button t-if="inDialogEdit" class="btn btn-xs btn-primary o_field_domain_dialog_button">Edit domain</button> </div> <div t-else="">Select a model to add a filter.</div> </t> - <t t-name="DomainNode.ControlPanel"> <div t-if="!widget.readonly && !widget.noControlPanel" class="o_domain_node_control_panel"> <button class="btn o_domain_delete_node_button"><i class="fa fa-times"/></button> @@ -800,8 +663,7 @@ </t> </div> </div> - -<div t-name="ModelFieldSelector" t-attf-class="o_field_selector#{!widget.options.readonly ? ' o_edit_mode' : ''}"> +<div t-name="ModelFieldSelector" t-attf-class="o_field_selector#{!widget.options.readonly ? ' o_edit_mode o_input' : ''}"> <div class="o_field_selector_value" tabindex="0"/> <div class="o_field_selector_controls" tabindex="0"> <i class="fa fa-exclamation-triangle o_field_selector_warning hidden" title="Invalid field chain"/> @@ -816,7 +678,7 @@ <ul class="o_field_selector_page"/> </div> <div t-if="widget.options.debugMode" class="o_field_selector_popover_footer"> - <input type="text"/> + <input type="text" class="o_input"/> </div> </div> </div> @@ -842,12 +704,11 @@ </li> </t> </ul> - <t t-name="web.datepicker"> <t t-set="placeholder" t-value="widget.getParent().node and widget.getParent().node.attrs.placeholder"/> <div class="o_datepicker"> <input type="text" - class="o_datepicker_input" + class="o_datepicker_input o_input" t-att-name="widget.name" t-att-placeholder="placeholder"/> <span class="o_datepicker_button"/> @@ -857,7 +718,7 @@ <span t-if="widget.mode === 'readonly'"/> <select t-if="widget.mode !== 'readonly'" - class="o_form_input" + class="o_input" t-att-name="widget.name" t-att-tabindex="widget.attrs.tabindex" t-att-autofocus="widget.attrs.autofocus" @@ -866,9 +727,9 @@ <t t-name="FieldRadio"> <span t-if="widget.mode === 'readonly'"/> - <div t-if="widget.mode !== 'readonly'" t-attf-class="o_form_field_radio #{widget.nodeOptions.horizontal ? 'o_horizontal' : 'o_vertical'}"> + <div t-if="widget.mode !== 'readonly'" t-attf-class="o_field_radio #{widget.nodeOptions.horizontal ? 'o_horizontal' : 'o_vertical'}"> <div t-foreach="widget.values" t-as="value" class="o_radio_item"> - <input type="radio" class="o_form_radio" t-att-id="widget.unique_id + '_' + value[0]" t-att-name="widget.unique_id" t-att-data-value="value[0]"/> + <input type="radio" class="o_radio_input" t-att-id="widget.unique_id + '_' + value[0]" t-att-name="widget.unique_id" t-att-data-value="value[0]"/> <label t-if="!widget.nodeOptions.no_radiolabel" class="o_form_label" t-att-for="widget.unique_id + '_' + value[0]"><t t-esc="value[1]"/></label> </div> </div> @@ -878,9 +739,9 @@ <a t-if="!widget.nodeOptions.no_open" class="o_form_uri" href="#"/> <span t-if="widget.nodeOptions.no_open"/> </t> - <div t-if="widget.mode === 'edit'" class="o_form_field o_form_field_many2one"> - <div class="o_form_input_dropdown"> - <input type="text" class="o_form_input" + <div t-if="widget.mode === 'edit'" class="o_field_widget o_field_many2one"> + <div class="o_input_dropdown"> + <input type="text" class="o_input" t-att-barcode_events="widget.nodeOptions.barcode_events" t-att-tabindex="widget.attrs.tabindex" t-att-autofocus="widget.attrs.autofocus" @@ -891,9 +752,6 @@ <button type="button" t-if="!widget.nodeOptions.no_open" class="fa fa-external-link btn btn-default o_external_button" tabindex="-1" draggable="false"/> </div> </t> -<t t-name="Many2OneButton.cell"> - <i t-attf-class="fa #{widget.icon}" t-att-title="widget.string"/> -</t> <t t-name="FieldMany2ManyTag"> <t t-foreach="elements" t-as="el"> <span t-attf-class="badge dropdown o_tag_color_#{el.color || 10}" t-att-data-color="el.color || 10" t-att-data-index="el_index" t-att-data-id="el.id"> @@ -915,19 +773,6 @@ </li> </ul> </t> -<t t-name="FieldBoolean"> - <div class="o_checkbox o_form_field_boolean"> - <input type="checkbox" - t-att-id="widget.idForLabel" - t-att-name="widget.name" - t-att-tabindex="widget.node.attrs.tabindex" - t-att-autofocus="widget.node.attrs.autofocus"/> - <span/> - </div> -</t> -<div t-name="FieldUpgradeBoolean" class="o_form_field o_form_field_boolean"> - <t t-call="FieldBoolean"/> -</div> <t t-name="ProgressBar"> <div class="o_progressbar"> <div t-if="widget.title" class="o_progressbar_title"><t t-esc="widget.title"/></div><div class="o_progress"> @@ -936,7 +781,7 @@ </div> </t> <t t-name="FieldPercentPie"> - <div class="o_form_field_percent_pie"> + <div class="o_field_percent_pie"> <div class="o_pie"> <div class="o_mask"/> <div class="o_mask"/> @@ -966,7 +811,7 @@ </button> </t> <t t-name="FieldBinaryImage"> - <div class="o_form_field_image"> + <div class="o_field_image"> <t t-if="widget.mode !== 'readonly'"> <div class="o_form_image_controls"> <span class="fa fa-pencil fa-lg pull-left o_select_file_button" title="Edit"/> @@ -997,8 +842,8 @@ <t t-name="FieldBinaryFile"> <a t-if="widget.mode === 'readonly'" href="javascript:void(0)" class="o_form_uri"/> - <div t-if="widget.mode !== 'readonly'" class="o_form_field_binary_file"> - <input type="text" class="o_form_input" + <div t-if="widget.mode !== 'readonly'" class="o_field_binary_file"> + <input type="text" class="o_input" readonly="readonly" t-att-name="widget.name" t-att-tabindex="widget.attrs.tabindex" @@ -1022,8 +867,8 @@ <input type="hidden" name="csrf_token" t-att-value="csrf_token"/> <input type="hidden" name="session_id" value="" t-if="widget.getSession().override_session"/> <input type="hidden" name="callback" t-att-value="fileupload_id"/> - <input t-if="widget.image_only" type="file" class="o_form_input_file" name="ufile" accept="image/*"/> - <input t-if="!widget.image_only" type="file" class="o_form_input_file" name="ufile" t-att="{'multiple': multi_upload ? 'multiple' : null}"/> + <input t-if="widget.image_only" type="file" class="o_input_file" name="ufile" accept="image/*"/> + <input t-if="!widget.image_only" type="file" class="o_input_file" name="ufile" t-att="{'multiple': multi_upload ? 'multiple' : null}"/> <t t-raw="0"/> </form> <iframe t-att-id="fileupload_id" t-att-name="fileupload_id" style="display: none"/> @@ -1089,7 +934,6 @@ <t t-name="SearchView.autocomplete"> <ul class="dropdown-menu o_searchview_autocomplete" role="menu"></ul> </t> - <div t-name="SearchView.FilterMenu" class="btn-group o_dropdown"> <button class="o_dropdown_toggler_btn btn btn-sm dropdown-toggle" data-toggle="dropdown"> <span class="fa fa-filter"/> Filters <span class="caret"/> @@ -1198,7 +1042,6 @@ </option> </select> </t> - <div t-name="SearchView.GroupByMenu" class="btn-group hidden-xs o_dropdown"> <button class="o_dropdown_toggler_btn btn btn-sm dropdown-toggle" data-toggle="dropdown"> <span class="fa fa-bars"/> Group By <span class="caret"/> @@ -1220,7 +1063,6 @@ <button type="button" class="btn btn-primary btn-sm o_add_group o_select_group">Apply</button> </li> </t> - <div t-name="SearchView.FavoriteMenu" class="btn-group o_dropdown"> <button class="o_dropdown_toggler_btn btn btn-sm dropdown-toggle" data-toggle="dropdown"> <span class="fa fa-star"/> Favorites <span class="caret"/> @@ -1334,13 +1176,6 @@ Name: <input class="oe_form_m2o_input_name" type="text"/> </div> </t> -<t t-name="FieldMonetary" t-extend="FieldChar"> - <t t-jquery="input"> - var $div = $(document.createElement('div')).attr('t-if', this.attr('t-if')).addClass('o_form_field_monetary'); - this.clone(true).appendTo($div); - this.replaceWith($div); - </t> -</t> <t t-name="FieldMany2ManyCheckBoxes"> <div> <div t-foreach="widget.m2mValues" t-as="m2m_value"> @@ -1352,31 +1187,16 @@ </div> </div> </t> -<t t-name="X2ManyCounter"> - <a href="javascript:void(0)"><t t-esc="text"/></a> -</t> <t t-name="StatInfo"> <span class="o_stat_value"><t t-esc="value"/></span> <span class="o_stat_text"><t t-esc="text"/></span> </t> - <t t-name="toggle_button"> <button type="button" class="o_icon_button" t-att-title="widget.string"> <i t-attf-class="fa #{widget.icon}" t-att-title="widget.string"/> </button> </t> -<t t-name="BooleanButton"> - <t t-if="widget.get_value()"> - <span class="o_stat_text o_not_hover text-success"><t t-esc="widget.string_true"/></span> - <span class="o_stat_text o_hover text-danger"><t t-esc="widget.hover_true"/></span> - </t> - <t t-if="!widget.get_value()"> - <span class="o_stat_text o_not_hover text-danger"><t t-esc="widget.string_false"/></span> - <span class="o_stat_text o_hover text-success"><t t-esc="widget.hover_false"/></span> - </t> -</t> - <div t-name="Pager"> <span class="o_pager_counter"> <span class="o_pager_value"></span> / <span class="o_pager_limit"></span> diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 02f59278786..54907582685 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -322,7 +322,7 @@ QUnit.module('basic_fields', { QUnit.module('FieldFloat'); - QUnit.test('float field when unset', function(assert) { + QUnit.test('float field when unset', function (assert) { assert.expect(1); var form = createView({ @@ -337,7 +337,7 @@ QUnit.module('basic_fields', { res_id: 4, }); - assert.ok(form.$('.o_form_field').hasClass('o_form_field_empty'), + assert.ok(form.$('.o_field_widget').hasClass('o_field_empty'), 'Non-set float field should be recognized as unset.'); form.destroy(); @@ -359,7 +359,7 @@ QUnit.module('basic_fields', { '</form>', res_id: 1, }); - assert.strictEqual(form.$('span.o_form_field_number:contains(0.4)').length, 1, + assert.strictEqual(form.$('span.o_field_number:contains(0.4)').length, 1, "should contain a number rounded to 1 decimal"); form.destroy(); }); @@ -379,22 +379,22 @@ QUnit.module('basic_fields', { res_id: 2, }); - assert.ok(!form.$('.o_form_field').hasClass('o_form_field_empty'), + assert.ok(!form.$('.o_field_widget').hasClass('o_field_empty'), 'Float field should be considered set for value 0.'); - assert.strictEqual(form.$('.o_form_field.o_form_field_number').first().text(), '0.000', + assert.strictEqual(form.$('.o_field_widget').first().text(), '0.000', 'The value should be displayed properly.'); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input.o_form_input').val(), '0.000', + assert.strictEqual(form.$('input').val(), '0.000', 'The value should be rendered with correct precision.'); - form.$('input.o_form_input').val('108.2458938598598').trigger('input'); - assert.strictEqual(form.$('input.o_form_input').val(), '108.2458938598598', + form.$('input').val('108.2458938598598').trigger('input'); + assert.strictEqual(form.$('input').val(), '108.2458938598598', 'The value should not be formated yet.'); - form.$('input.o_form_input').val('18.8958938598598').trigger('input'); + form.$('input').val('18.8958938598598').trigger('input'); form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field.o_form_field_number').first().text(), '18.896', + assert.strictEqual(form.$('.o_field_widget').first().text(), '18.896', 'The new value should be rounded properly.'); form.destroy(); @@ -420,23 +420,23 @@ QUnit.module('basic_fields', { var $cell = list.$('tr.o_data_row td:not(.o_list_record_selector)').first(); $cell.click(); - assert.strictEqual(list.$('input.o_form_input').length, 1, + assert.strictEqual(list.$('input[name="qux"]').length, 1, 'The view should have 1 input for editable float.'); - list.$('input.o_form_input').val('108.2458938598598').trigger('input'); - assert.strictEqual(list.$('input.o_form_input').val(), '108.2458938598598', + list.$('input[name="qux"]').val('108.2458938598598').trigger('input'); + assert.strictEqual(list.$('input[name="qux"]').val(), '108.2458938598598', 'The value should not be formated yet.'); - list.$('input.o_form_input').val('18.8958938598598').trigger('input'); + list.$('input[name="qux"]').val('18.8958938598598').trigger('input'); list.$buttons.find('.o_list_button_save').click(); - assert.strictEqual(list.$('.o_form_field.o_form_field_number').first().text(), '18.896', + assert.strictEqual(list.$('.o_field_widget').first().text(), '18.896', 'The new value should be rounded properly.'); list.destroy(); }); - QUnit.module('EmailWidget'); + QUnit.module('FieldEmail'); QUnit.test('email field in form view', function (assert) { assert.expect(7); @@ -455,7 +455,7 @@ QUnit.module('basic_fields', { res_id: 1, }); - var $mailtoLink = form.$('a.o_form_uri.o_form_field.o_text_overflow'); + var $mailtoLink = form.$('a.o_form_uri.o_field_widget.o_text_overflow'); assert.strictEqual($mailtoLink.length, 1, "should have a anchor with correct classes"); assert.strictEqual($mailtoLink.text(), 'yop', @@ -465,17 +465,17 @@ QUnit.module('basic_fields', { // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input[type="text"].o_form_input.o_form_field').length, 1, + assert.strictEqual(form.$('input[type="text"].o_field_widget').length, 1, "should have an input for the email field"); - assert.strictEqual(form.$('input[type="text"].o_form_input.o_form_field').val(), 'yop', + assert.strictEqual(form.$('input[type="text"].o_field_widget').val(), 'yop', "input should contain field value in edit mode"); // change value in edit mode - form.$('input[type="text"].o_form_input.o_form_field').val('new').trigger('input'); + form.$('input[type="text"].o_field_widget').val('new').trigger('input'); // save form.$buttons.find('.o_form_button_save').click(); - $mailtoLink = form.$('a.o_form_uri.o_form_field.o_text_overflow'); + $mailtoLink = form.$('a.o_form_uri.o_field_widget.o_text_overflow'); assert.strictEqual($mailtoLink.text(), 'new', "new value should be displayed properly"); assert.strictEqual($mailtoLink.attr('href'), 'mailto:new', @@ -567,22 +567,22 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.strictEqual(form.$('.o_form_field').text(), 'yop', + assert.strictEqual(form.$('.o_field_widget').text(), 'yop', "the value should be displayed properly"); // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input[type="text"].o_form_input.o_form_field').length, 1, + assert.strictEqual(form.$('input[type="text"].o_field_widget').length, 1, "should have an input for the char field"); - assert.strictEqual(form.$('input[type="text"].o_form_input.o_form_field').val(), 'yop', + assert.strictEqual(form.$('input[type="text"].o_field_widget').val(), 'yop', "input should contain field value in edit mode"); // change value in edit mode - form.$('input[type="text"].o_form_input.o_form_field').val('limbo').trigger('input'); + form.$('input[type="text"].o_field_widget').val('limbo').trigger('input'); // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field').text(), 'limbo', + assert.strictEqual(form.$('.o_field_widget').text(), 'limbo', 'the new value should be displayed'); form.destroy(); }); @@ -639,30 +639,30 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.strictEqual(form.$('a.o_form_uri.o_form_field.o_text_overflow').length, 1, + assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').length, 1, "should have a anchor with correct classes"); - assert.strictEqual(form.$('a.o_form_uri.o_form_field.o_text_overflow').attr('href'), 'yop', + assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').attr('href'), 'yop', "should have proper href link"); - assert.strictEqual(form.$('a.o_form_uri.o_form_field.o_text_overflow').text(), 'yop', + assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').text(), 'yop', "the value should be displayed properly"); // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input[type="text"].o_form_input.o_form_field').length, 1, + assert.strictEqual(form.$('input[type="text"].o_field_widget').length, 1, "should have an input for the char field"); - assert.strictEqual(form.$('input[type="text"].o_form_input.o_form_field').val(), 'yop', + assert.strictEqual(form.$('input[type="text"].o_field_widget').val(), 'yop', "input should contain field value in edit mode"); // change value in edit mode - form.$('input[type="text"].o_form_input.o_form_field').val('limbo').trigger('input'); + form.$('input[type="text"].o_field_widget').val('limbo').trigger('input'); // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('a.o_form_uri.o_form_field.o_text_overflow').length, 1, + assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').length, 1, "should still have a anchor with correct classes"); - assert.strictEqual(form.$('a.o_form_uri.o_form_field.o_text_overflow').attr('href'), 'limbo', + assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').attr('href'), 'limbo', "should have proper new href link"); - assert.strictEqual(form.$('a.o_form_uri.o_form_field.o_text_overflow').text(), 'limbo', + assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').text(), 'limbo', 'the new value should be displayed'); form.destroy(); @@ -727,12 +727,12 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.ok(form.$('div.o_form_textarea').length, "should have a text area"); - assert.strictEqual(form.$('div.o_form_textarea').text(), 'yop', 'should be "yop" in readonly'); + assert.ok(form.$('div.o_field_text').length, "should have a text area"); + assert.strictEqual(form.$('div.o_field_text').text(), 'yop', 'should be "yop" in readonly'); form.$buttons.find('.o_form_button_edit').click(); - var $textarea = form.$('.o_form_textarea textarea'); + var $textarea = form.$('textarea.o_field_text'); assert.ok($textarea.length, "should have a text area"); assert.strictEqual($textarea.val(), 'yop', 'should still be "yop" in edit'); @@ -744,7 +744,7 @@ QUnit.module('basic_fields', { form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('div.o_form_textarea').text(), 'hello world', + assert.strictEqual(form.$('div.o_field_text').text(), 'hello world', 'should be "hello world" after save'); form.destroy(); }); @@ -764,7 +764,7 @@ QUnit.module('basic_fields', { res_id: 1, }); - var $field = form.$('div.o_list_text'); + var $field = form.$('div.o_field_text'); assert.strictEqual($field.outerHeight(), $field[0].scrollHeight, "text field should not have a scroll bar"); @@ -805,27 +805,27 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.strictEqual(form.$('a.o_form_field[name="document"] > .fa-download').length, 1, + assert.strictEqual(form.$('a.o_field_widget[name="document"] > .fa-download').length, 1, "the binary field should be rendered as a downloadable link in readonly"); - form.$('a.o_form_field[name="document"]').click(); + form.$('a.o_field_widget[name="document"]').click(); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('a.o_form_field[name="document"] > .fa-download').length, 0, + assert.strictEqual(form.$('a.o_field_widget[name="document"] > .fa-download').length, 0, "the binary field should not be rendered as a downloadable link in edit"); - assert.strictEqual(form.$('div.o_form_field_binary_file[name="document"]').length, 1, + assert.strictEqual(form.$('div.o_field_binary_file[name="document"]').length, 1, "the binary field should be correctly rendered in edit"); - assert.strictEqual(form.$('.o_form_field_binary_file > input').attr('readonly'), 'readonly', + assert.strictEqual(form.$('.o_field_binary_file > input').attr('readonly'), 'readonly', "the input should be readonly"); - assert.strictEqual(form.$('.o_form_field_binary_file > .o_clear_file_button').length, 1, + assert.strictEqual(form.$('.o_field_binary_file > .o_clear_file_button').length, 1, "there shoud be a button to clear the file"); - form.$('.o_form_field_binary_file > .o_clear_file_button').click(); + form.$('.o_field_binary_file > .o_clear_file_button').click(); - assert.ok(form.$('.o_form_field_binary_file > input').hasClass('o_hidden'), + assert.ok(form.$('.o_field_binary_file > input').hasClass('o_hidden'), "the input should be hidden"); - assert.strictEqual(form.$('.o_form_field_binary_file > .o_select_file_button:not(.o_hidden)').length, 1, + assert.strictEqual(form.$('.o_field_binary_file > .o_select_file_button:not(.o_hidden)').length, 1, "there shoud be a button to upload the file"); form.destroy(); @@ -1106,7 +1106,7 @@ QUnit.module('basic_fields', { arch:'<form string="Partners"><field name="date"/></form>', res_id: 4, }); - var $span = form.$('span.o_form_field'); + var $span = form.$('span.o_field_widget'); assert.strictEqual($span.length, 1, "should have one span in the form view"); assert.strictEqual($span.text(), "", "and it should be empty"); form.destroy(); @@ -1135,7 +1135,7 @@ QUnit.module('basic_fields', { }, }); - assert.strictEqual(form.$('.o_form_field_date').text(), '02/03/2017', + assert.strictEqual(form.$('.o_field_date').text(), '02/03/2017', 'the date should be correctly displayed in readonly'); // switch to edit mode @@ -1157,7 +1157,7 @@ QUnit.module('basic_fields', { // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field_date').text(), '02/22/2017', + assert.strictEqual(form.$('.o_field_date').text(), '02/22/2017', 'the selected date should be displayed after saving'); form.destroy(); }); @@ -1244,7 +1244,7 @@ QUnit.module('basic_fields', { // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field_date').text(), '', + assert.strictEqual(form.$('.o_field_date').text(), '', 'the selected date should be displayed after saving'); form.destroy(); }); @@ -1252,7 +1252,7 @@ QUnit.module('basic_fields', { QUnit.module('FieldDatetime'); - QUnit.test('datetime field in form view', function(assert) { + QUnit.test('datetime field in form view', function (assert) { assert.expect(6); var form = createView({ @@ -1271,7 +1271,7 @@ QUnit.module('basic_fields', { }); var expectedDateString = "02/08/2017 12:00:00"; // 10:00:00 without timezone - assert.strictEqual(form.$('.o_form_field_date').text(), expectedDateString, + assert.strictEqual(form.$('.o_field_date').text(), expectedDateString, 'the datetime should be correctly displayed in readonly'); // switch to edit mode @@ -1302,7 +1302,7 @@ QUnit.module('basic_fields', { // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field_date').text(), newExpectedDateString, + assert.strictEqual(form.$('.o_field_date').text(), newExpectedDateString, 'the selected date should be displayed after saving'); form.destroy(); @@ -1407,7 +1407,7 @@ QUnit.module('basic_fields', { // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field_date').text(), '', + assert.strictEqual(form.$('.o_field_date').text(), '', 'the selected date should be displayed after saving'); form.destroy(); }); @@ -1415,7 +1415,7 @@ QUnit.module('basic_fields', { QUnit.module('FieldMonetary'); - QUnit.test('monetary field in form view', function(assert) { + QUnit.test('monetary field in form view', function (assert) { assert.expect(5); var form = createView({ @@ -1435,28 +1435,28 @@ QUnit.module('basic_fields', { }); // Non-breaking space between the currency and the amount - assert.strictEqual(form.$('.o_form_field').first().text(), '$\u00a09.10', + assert.strictEqual(form.$('.o_field_widget').first().text(), '$\u00a09.10', 'The value should be displayed properly.'); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input.o_form_input').first().val(), '9.10', + assert.strictEqual(form.$('input').val(), '9.10', 'The input should be rendered without the currency symbol.'); - assert.strictEqual(form.$('input.o_form_input').parent().children().first().text(), '$', + assert.strictEqual(form.$('input').parent().children().first().text(), '$', 'The input should be preceded by a span containing the currency symbol.'); - form.$('input.o_form_input').first().val('108.2458938598598').trigger('input'); - assert.strictEqual(form.$('input.o_form_input').val(), '108.2458938598598', + form.$('input').val('108.2458938598598').trigger('input'); + assert.strictEqual(form.$('input').val(), '108.2458938598598', 'The value should not be formated yet.'); form.$buttons.find('.o_form_button_save').click(); // Non-breaking space between the currency and the amount - assert.strictEqual(form.$('.o_form_field').first().text(), '$\u00a0108.25', + assert.strictEqual(form.$('.o_field_widget').first().text(), '$\u00a0108.25', 'The new value should be rounded properly.'); form.destroy(); }); - QUnit.test('monetary field with currency symbol after', function(assert) { + QUnit.test('monetary field with currency symbol after', function (assert) { assert.expect(5); var form = createView({ @@ -1476,22 +1476,22 @@ QUnit.module('basic_fields', { }); // Non-breaking space between the currency and the amount - assert.strictEqual(form.$('.o_form_field').first().text(), '0.00\u00a0€', + assert.strictEqual(form.$('.o_field_widget').first().text(), '0.00\u00a0€', 'The value should be displayed properly.'); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input.o_form_input').first().val(), '0.00', + assert.strictEqual(form.$('input').first().val(), '0.00', 'The input should be rendered without the currency symbol.'); - assert.strictEqual(form.$('input.o_form_input').parent().children().eq(1).text(), '€', + assert.strictEqual(form.$('input').parent().children().eq(1).text(), '€', 'The input should be followed by a span containing the currency symbol.'); - form.$('input.o_form_input').first().val('108.2458938598598').trigger('input'); - assert.strictEqual(form.$('input.o_form_input').first().val(), '108.2458938598598', + form.$('input').first().val('108.2458938598598').trigger('input'); + assert.strictEqual(form.$('input').first().val(), '108.2458938598598', 'The value should not be formated yet.'); form.$buttons.find('.o_form_button_save').click(); // Non-breaking space between the currency and the amount - assert.strictEqual(form.$('.o_form_field').first().text(), '108.25\u00a0€', + assert.strictEqual(form.$('.o_field_widget').first().text(), '108.25\u00a0€', 'The new value should be rounded properly.'); form.destroy(); @@ -1513,15 +1513,15 @@ QUnit.module('basic_fields', { }, }); - var dollarValues = list.$('td').filter(function() {return _.str.include($(this).text(), '$')}); + var dollarValues = list.$('td').filter(function () {return _.str.include($(this).text(), '$');}); assert.strictEqual(dollarValues.length, 1, 'Only one line has dollar as a currency.'); - var euroValues = list.$('td').filter(function() {return _.str.include($(this).text(), '€')}); + var euroValues = list.$('td').filter(function () {return _.str.include($(this).text(), '€');}); assert.strictEqual(euroValues.length, 1, 'One one line has euro as a currency.'); - var zeroValues = list.$('td').filter(function() {return _.str.include($(this).text(), '0.00')}); + var zeroValues = list.$('td').filter(function () {return _.str.include($(this).text(), '0.00');}); assert.strictEqual(zeroValues.length, 2, 'Unset float values should be rendered as zeros.'); @@ -1531,15 +1531,15 @@ QUnit.module('basic_fields', { assert.strictEqual($cell.children().length, 1, 'The cell td should only contain the special div of monetary widget.'); - assert.strictEqual(list.$('input.o_form_input').length, 1, + assert.strictEqual(list.$('[name="qux"] input').length, 1, 'The view should have 1 input for editable monetary float.'); - assert.strictEqual(list.$('input.o_form_input').val(), '9.10', + assert.strictEqual(list.$('[name="qux"] input').val(), '9.10', 'The input should be rendered without the currency symbol.'); - assert.strictEqual(list.$('input.o_form_input').parent().children().first().text(), '$', + assert.strictEqual(list.$('[name="qux"] input').parent().children().first().text(), '$', 'The input should be preceded by a span containing the currency symbol.'); - list.$('input.o_form_input').val('108.2458938598598').trigger('input'); - assert.strictEqual(list.$('input.o_form_input').val(), '108.2458938598598', + list.$('[name="qux"] input').val('108.2458938598598').trigger('input'); + assert.strictEqual(list.$('[name="qux"] input').val(), '108.2458938598598', 'The typed value should be correctly displayed.'); list.$buttons.find('.o_list_button_save').click(); @@ -1577,22 +1577,22 @@ QUnit.module('basic_fields', { }, }); - assert.strictEqual(form.$('.o_form_field_monetary').html(), "$ 9.10", + assert.strictEqual(form.$('.o_field_monetary').html(), "$ 9.10", "readonly value should contain the currency"); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field_monetary > input').val(), "9.10", + assert.strictEqual(form.$('.o_field_monetary > input').val(), "9.10", "input value in edition should only contain the value, without the currency"); form.$('input[type="checkbox"]').click(); // Change the field on which the monetary depends - assert.strictEqual(form.$('.o_form_field_monetary > input').length, 1, + assert.strictEqual(form.$('.o_field_monetary > input').length, 1, "After the onchange, the monetary <input/> should not have been duplicated"); - var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget'); - form.$('.o_form_field_many2one input').click(); + var $dropdown = form.$('.o_field_many2one input').autocomplete('widget'); + form.$('.o_field_many2one input').click(); $dropdown.find('li:not(.o_m2o_dropdown_option):last').mouseenter().click(); - assert.strictEqual(form.$('.o_form_field_monetary > span').html(), "€", + assert.strictEqual(form.$('.o_field_monetary > span').html(), "€", "After currency change, the monetary field currency should have been updated"); form.destroy(); @@ -1600,7 +1600,7 @@ QUnit.module('basic_fields', { QUnit.module('FieldInteger'); - QUnit.test('integer field when unset', function(assert) { + QUnit.test('integer field when unset', function (assert) { assert.expect(1); var form = createView({ @@ -1611,13 +1611,13 @@ QUnit.module('basic_fields', { res_id: 4, }); - assert.ok(form.$('.o_form_field').hasClass('o_form_field_empty'), + assert.ok(form.$('.o_field_widget').hasClass('o_field_empty'), 'Non-set integer field should be recognized as unset.'); form.destroy(); }); - QUnit.test('integer field in form view', function(assert) { + QUnit.test('integer field in form view', function (assert) { assert.expect(4); var form = createView({ @@ -1628,25 +1628,25 @@ QUnit.module('basic_fields', { res_id: 2, }); - assert.ok(!form.$('.o_form_field').hasClass('o_form_field_empty'), + assert.ok(!form.$('.o_field_widget').hasClass('o_field_empty'), 'Integer field should be considered set for value 0.'); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input.o_form_input').val(), '0', - 'The value should be rendered correctly in edit mode.') + assert.strictEqual(form.$('input').val(), '0', + 'The value should be rendered correctly in edit mode.'); - form.$('input.o_form_input').val('-18').trigger('input'); - assert.strictEqual(form.$('input.o_form_input').val(), '-18', - 'The value should be correctly displayed in the input.') + form.$('input').val('-18').trigger('input'); + assert.strictEqual(form.$('input').val(), '-18', + 'The value should be correctly displayed in the input.'); form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field').text(), '-18', - 'The new value should be saved and displayed properly.') + assert.strictEqual(form.$('.o_field_widget').text(), '-18', + 'The new value should be saved and displayed properly.'); form.destroy(); }); - QUnit.test('integer field in form view with virtual id', function(assert) { + QUnit.test('integer field in form view with virtual id', function (assert) { assert.expect(2); var params = { View: FormView, @@ -1657,7 +1657,7 @@ QUnit.module('basic_fields', { params.res_id = this.data.partner.records[1].id = "2-20170808020000"; var form = createView(params); - assert.strictEqual(form.$('.o_form_field').text(), "2-20170808020000", + assert.strictEqual(form.$('.o_field_widget').text(), "2-20170808020000", "Should display virtual id"); form.destroy(); @@ -1683,7 +1683,7 @@ QUnit.module('basic_fields', { '</tree>', }); - var zeroValues = list.$('td').filter(function() {return $(this).text() === '0'}); + var zeroValues = list.$('td').filter(function () {return $(this).text() === '0';}); assert.strictEqual(zeroValues.length, 1, 'Unset integer values should not be rendered as zeros.'); @@ -1691,16 +1691,16 @@ QUnit.module('basic_fields', { var $cell = list.$('tr.o_data_row td:not(.o_list_record_selector)').first(); $cell.click(); - assert.strictEqual(list.$('input.o_form_input').length, 1, - 'The view should have 1 input for editable integer.') + assert.strictEqual(list.$('input[name="int_field"]').length, 1, + 'The view should have 1 input for editable integer.'); - list.$('input.o_form_input').val('-28').trigger('input'); - assert.strictEqual(list.$('input.o_form_input').val(), '-28', - 'The value should be displayed properly in the input.') + list.$('input[name="int_field"]').val('-28').trigger('input'); + assert.strictEqual(list.$('input[name="int_field"]').val(), '-28', + 'The value should be displayed properly in the input.'); list.$buttons.find('.o_list_button_save').click(); assert.strictEqual(list.$('td:not(.o_list_record_selector)').first().text(), '-28', - 'The new value should be saved and displayed properly.') + 'The new value should be saved and displayed properly.'); list.destroy(); }); @@ -1708,7 +1708,7 @@ QUnit.module('basic_fields', { QUnit.module('FieldFloatTime'); - QUnit.test('float_time field in form view', function(assert) { + QUnit.test('float_time field in form view', function (assert) { assert.expect(5); var form = createView({ @@ -1731,20 +1731,20 @@ QUnit.module('basic_fields', { }); // 9 + 0.1 * 60 = 9.06 - assert.strictEqual(form.$('.o_form_field').first().text(), '09:06', - 'The formatted time value should be displayed properly.') + assert.strictEqual(form.$('.o_field_widget').first().text(), '09:06', + 'The formatted time value should be displayed properly.'); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input.o_form_input').val(), '09:06', - 'The value should be rendered correctly in the input.') + assert.strictEqual(form.$('input').val(), '09:06', + 'The value should be rendered correctly in the input.'); - form.$('input.o_form_input').val('-11:48').trigger('input'); - assert.strictEqual(form.$('input.o_form_input').val(), '-11:48', - 'The new value should be displayed properly in the input.') + form.$('input').val('-11:48').trigger('input'); + assert.strictEqual(form.$('input').val(), '-11:48', + 'The new value should be displayed properly in the input.'); form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field').first().text(), '-11:48', - 'The new value should be saved and displayed properly.') + assert.strictEqual(form.$('.o_field_widget').first().text(), '-11:48', + 'The new value should be saved and displayed properly.'); form.destroy(); }); @@ -1775,7 +1775,7 @@ QUnit.module('basic_fields', { }, }); - var $phoneLink = form.$('a.o_form_uri.o_form_field.o_text_overflow'); + var $phoneLink = form.$('a.o_form_uri.o_field_widget.o_text_overflow'); assert.strictEqual($phoneLink.length, 1, "should have a anchor with correct classes"); assert.strictEqual($phoneLink.text(), 'y\u00ADop', @@ -1785,17 +1785,17 @@ QUnit.module('basic_fields', { // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input[type="text"].o_form_input.o_form_field').length, 1, + assert.strictEqual(form.$('input[type="text"].o_field_widget').length, 1, "should have an input for the phone field"); - assert.strictEqual(form.$('input[type="text"].o_form_input.o_form_field').val(), 'yop', + assert.strictEqual(form.$('input[type="text"].o_field_widget').val(), 'yop', "input should contain field value in edit mode"); // change value in edit mode - form.$('input[type="text"].o_form_input.o_form_field').val('new').trigger('input'); + form.$('input[type="text"].o_field_widget').val('new').trigger('input'); // save form.$buttons.find('.o_form_button_save').click(); - $phoneLink = form.$('a.o_form_uri.o_form_field.o_text_overflow'); + $phoneLink = form.$('a.o_form_uri.o_field_widget.o_text_overflow'); assert.strictEqual($phoneLink.text(), 'n\u00ADew', "new value should be displayed properly as text with the skype obfuscation"); assert.strictEqual($phoneLink.attr('href'), 'tel:new', @@ -1804,7 +1804,7 @@ QUnit.module('basic_fields', { form.destroy(); }); - QUnit.test('phone field in editable list view on extra small screens', function(assert) { + QUnit.test('phone field in editable list view on extra small screens', function (assert) { assert.expect(10); var list = createView({ @@ -1885,7 +1885,7 @@ QUnit.module('basic_fields', { }, }); - var $phone = form.$('span.o_form_field.o_text_overflow:not(.o_form_uri)'); + var $phone = form.$('span.o_field_widget.o_text_overflow:not(.o_form_uri)'); assert.strictEqual($phone.length, 1, "should have a simple span rather than a link"); assert.strictEqual($phone.text(), 'yop', @@ -1893,23 +1893,23 @@ QUnit.module('basic_fields', { // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input[type="text"].o_form_input.o_form_field').length, 1, + assert.strictEqual(form.$('input[type="text"].o_field_widget').length, 1, "should have an input for the phone field"); - assert.strictEqual(form.$('input[type="text"].o_form_input.o_form_field').val(), 'yop', + assert.strictEqual(form.$('input[type="text"].o_field_widget').val(), 'yop', "input should contain field value in edit mode"); // change value in edit mode - form.$('input[type="text"].o_form_input.o_form_field').val('new').trigger('input'); + form.$('input[type="text"].o_field_widget').val('new').trigger('input'); // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('span.o_form_field.o_text_overflow:not(.o_form_uri)').text(), 'new', + assert.strictEqual(form.$('span.o_field_widget.o_text_overflow:not(.o_form_uri)').text(), 'new', "new value should be displayed properly as text without skype obfuscation"); form.destroy(); }); - QUnit.test('phone field in editable list view on normal screens', function(assert) { + QUnit.test('phone field in editable list view on normal screens', function (assert) { // The behavior of this widget is completely altered by crm_voip so this // test is irrelevant and fails if crm_voip is installed. The enterprise // module is responsible for testing its own behavior in its own tests. @@ -1981,13 +1981,13 @@ QUnit.module('basic_fields', { res_id: 2, }); - assert.strictEqual(form.$('.o_form_field.o_priority:not(.o_form_field_empty)').length, 1, + assert.strictEqual(form.$('.o_field_widget.o_priority:not(.o_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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.o_priority').find('a.o_priority_star.fa-star-o').length, 2, "should have two empty stars since there is no value"); form.destroy(); @@ -2010,22 +2010,22 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.strictEqual(form.$('.o_form_field.o_priority:not(.o_form_field_empty)').length, 1, + assert.strictEqual(form.$('.o_field_widget.o_priority:not(.o_field_empty)').length, 1, "widget should be considered set"); - assert.strictEqual(form.$('.o_form_field.o_priority').find('a.o_priority_star').length, 2, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + form.$('.o_field_widget.o_priority a.o_priority_star.fa-star-o').last().trigger('mouseover'); + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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 @@ -2033,54 +2033,54 @@ QUnit.module('basic_fields', { // 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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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(); + form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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, + assert.strictEqual(form.$('.o_field_widget.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) { + QUnit.test('priority widget in editable list view', function (assert) { assert.expect(25); var list = createView({ @@ -2090,7 +2090,7 @@ QUnit.module('basic_fields', { arch: '<tree editable="bottom"><field name="selection" widget="priority"/></tree>', }); - assert.strictEqual(list.$('.o_data_row').first().find('.o_priority:not(.o_form_field_empty)').length, 1, + assert.strictEqual(list.$('.o_data_row').first().find('.o_priority:not(.o_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"); @@ -2141,7 +2141,7 @@ QUnit.module('basic_fields', { "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 = 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, @@ -2193,15 +2193,15 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status.o_status_red').length, 1, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status.o_status_red').length, 1, "should have one red status since selection is the second, blocked state"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status.o_status_green').length, 0, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status.o_status_green').length, 0, "should not have one green status since selection is the second, blocked state"); assert.strictEqual(form.$('ul.dropdown-menu.state:visible').length, 0, "there should not be a dropdown"); // Click on the status button to make the dropdown appear - form.$('.o_form_field.o_selection .o_status').first().click(); + form.$('.o_field_widget.o_selection .o_status').first().click(); assert.strictEqual(form.$('ul.dropdown-menu.state:visible').length, 1, "there should be a dropdown"); assert.strictEqual(form.$('ul.dropdown-menu.state:visible li').length, 2, @@ -2211,26 +2211,26 @@ QUnit.module('basic_fields', { form.$('ul.dropdown-menu.state:visible li').first().click(); assert.strictEqual(form.$('ul.dropdown-menu.state:visible').length, 0, "there should not be a dropdown anymore"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status.o_status_red').length, 0, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status.o_status_red').length, 0, "should not have one red status since selection is the first, normal state"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status.o_status_green').length, 0, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status.o_status_green').length, 0, "should not have one green status since selection is the first, normal state"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status').length, 1, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status').length, 1, "should have one grey status since selection is the first, normal state"); // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); assert.strictEqual(form.$('ul.dropdown-menu.state:visible').length, 0, "there should still not be a dropdown"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status.o_status_red').length, 0, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status.o_status_red').length, 0, "should still not have one red status since selection is the first, normal state"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status.o_status_green').length, 0, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status.o_status_green').length, 0, "should still not have one green status since selection is the first, normal state"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status').length, 1, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status').length, 1, "should still have one grey status since selection is the first, normal state"); // Click on the status button to make the dropdown appear - form.$('.o_form_field.o_selection .o_status').first().click(); + form.$('.o_field_widget.o_selection .o_status').first().click(); assert.strictEqual(form.$('ul.dropdown-menu.state:visible').length, 1, "there should be a dropdown"); assert.strictEqual(form.$('ul.dropdown-menu.state:visible li').length, 2, @@ -2240,18 +2240,18 @@ QUnit.module('basic_fields', { form.$('ul.dropdown-menu.state:visible li').last().click(); assert.strictEqual(form.$('ul.dropdown-menu.state:visible').length, 0, "there should not be a dropdown anymore"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status.o_status_red').length, 0, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status.o_status_red').length, 0, "should not have one red status since selection is the third, done state"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status.o_status_green').length, 1, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status.o_status_green').length, 1, "should have one green status since selection is the third, done state"); // save form.$buttons.find('.o_form_button_save').click(); assert.strictEqual(form.$('ul.dropdown-menu.state:visible').length, 0, "there should still not be a dropdown anymore"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status.o_status_red').length, 0, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status.o_status_red').length, 0, "should still not have one red status since selection is the third, done state"); - assert.strictEqual(form.$('.o_form_field.o_selection > a span.o_status.o_status_green').length, 1, + assert.strictEqual(form.$('.o_field_widget.o_selection > a span.o_status.o_status_green').length, 1, "should still have one green status since selection is the third, done state"); form.destroy(); @@ -2387,41 +2387,41 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.strictEqual(form.$('.o_form_field.label.label-warning').length, 1, + assert.strictEqual(form.$('.o_field_widget.label.label-warning').length, 1, "should have a warning status label since selection is the second, blocked state"); - assert.strictEqual(form.$('.o_form_field.label.label-default').length, 0, + assert.strictEqual(form.$('.o_field_widget.label.label-default').length, 0, "should not have a default status since selection is the second, blocked state"); - assert.strictEqual(form.$('.o_form_field.label.label-success').length, 0, + assert.strictEqual(form.$('.o_field_widget.label.label-success').length, 0, "should not have a success status since selection is the second, blocked state"); - assert.strictEqual(form.$('.o_form_field.label.label-warning').text(), 'Blocked', + assert.strictEqual(form.$('.o_field_widget.label.label-warning').text(), 'Blocked', "the label should say 'Blocked' since this is the label value for that state"); // // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field.label.label-warning').length, 1, + assert.strictEqual(form.$('.o_field_widget.label.label-warning').length, 1, "should have a warning status label since selection is the second, blocked state"); - assert.strictEqual(form.$('.o_form_field.label.label-default').length, 0, + assert.strictEqual(form.$('.o_field_widget.label.label-default').length, 0, "should not have a default status since selection is the second, blocked state"); - assert.strictEqual(form.$('.o_form_field.label.label-success').length, 0, + assert.strictEqual(form.$('.o_field_widget.label.label-success').length, 0, "should not have a success status since selection is the second, blocked state"); - assert.strictEqual(form.$('.o_form_field.label.label-warning').text(), 'Blocked', + assert.strictEqual(form.$('.o_field_widget.label.label-warning').text(), 'Blocked', "the label should say 'Blocked' since this is the label value for that state"); // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field.label.label-warning').length, 1, + assert.strictEqual(form.$('.o_field_widget.label.label-warning').length, 1, "should have a warning status label since selection is the second, blocked state"); - assert.strictEqual(form.$('.o_form_field.label.label-default').length, 0, + assert.strictEqual(form.$('.o_field_widget.label.label-default').length, 0, "should not have a default status since selection is the second, blocked state"); - assert.strictEqual(form.$('.o_form_field.label.label-success').length, 0, + assert.strictEqual(form.$('.o_field_widget.label.label-success').length, 0, "should not have a success status since selection is the second, blocked state"); - assert.strictEqual(form.$('.o_form_field.label.label-warning').text(), 'Blocked', + assert.strictEqual(form.$('.o_field_widget.label.label-warning').text(), 'Blocked', "the label should say 'Blocked' since this is the label value for that state"); form.destroy(); }); - QUnit.test('label_selection widget in editable list view', function(assert) { + QUnit.test('label_selection widget in editable list view', function (assert) { assert.expect(21); var list = createView({ @@ -2512,29 +2512,29 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info').length, 1, + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info').length, 1, "should have one stat button"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_value').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_value').text(), '10', "should have 10 as value"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_text').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_text').text(), 'int_field', "should have 'int_field' as text"); // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info').length, 1, + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info').length, 1, "should still have one stat button"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_value').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_value').text(), '10', "should still have 10 as value"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_text').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_text').text(), 'int_field', "should have 'int_field' as text"); // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info').length, 1, + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info').length, 1, "should have one stat button"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_value').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_value').text(), '10', "should have 10 as value"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_text').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_text').text(), 'int_field', "should have 'int_field' as text"); form.destroy(); @@ -2564,29 +2564,29 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info').length, 1, + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info').length, 1, "should have one stat button"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_value').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_value').text(), '10', "should have 10 as value"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_text').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_text').text(), 'yop', "should have 'yop' as text, since it is the value of field foo"); // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info').length, 1, + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info').length, 1, "should still have one stat button"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_value').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_value').text(), '10', "should still have 10 as value"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_text').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_text').text(), 'yop', "should have 'yop' as text, since it is the value of field foo"); // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info').length, 1, + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info').length, 1, "should have one stat button"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_value').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_value').text(), '10', "should have 10 as value"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_text').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_text').text(), 'yop', "should have 'yop' as text, since it is the value of field foo"); form.destroy(); @@ -2615,29 +2615,29 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info').length, 1, + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info').length, 1, "should have one stat button"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_value').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_value').text(), '10', "should have 10 as value"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_text').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_text').text(), '', "should not have any label"); // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info').length, 1, + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info').length, 1, "should still have one stat button"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_value').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_value').text(), '10', "should still have 10 as value"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_text').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_text').text(), '', "should not have any label"); // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info').length, 1, + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info').length, 1, "should have one stat button"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_value').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_value').text(), '10', "should have 10 as value"); - assert.strictEqual(form.$('.oe_stat_button .o_form_field.o_stat_info .o_stat_text').text(), + assert.strictEqual(form.$('.oe_stat_button .o_field_widget.o_stat_info .o_stat_text').text(), '', "should not have any label"); form.destroy(); @@ -2663,35 +2663,35 @@ QUnit.module('basic_fields', { res_id: 1, }); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie').length, 1, + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie').length, 1, "should have a pie chart"); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_pie_value').text(), + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_pie_value').text(), '10%', "should have 10% as pie value since int_field=10"); - assert.ok(_.str.include(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').first().attr('style'), + assert.ok(_.str.include(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').first().attr('style'), 'transform: rotate(180deg);'), "left mask should be covering the whole left side of the pie"); - assert.ok(_.str.include(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').last().attr('style'), + assert.ok(_.str.include(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').last().attr('style'), 'transform: rotate(36deg);'), "right mask should be rotated from 360*(10/100) = 36 degrees"); // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie').length, 1, + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie').length, 1, "should have a pie chart"); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_pie_value').text(), + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_pie_value').text(), '10%', "should have 10% as pie value since int_field=10"); - assert.ok(_.str.include(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').first().attr('style'), + assert.ok(_.str.include(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').first().attr('style'), 'transform: rotate(180deg);'), "left mask should be covering the whole left side of the pie"); - assert.ok(_.str.include(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').last().attr('style'), + assert.ok(_.str.include(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').last().attr('style'), 'transform: rotate(36deg);'), "right mask should be rotated from 360*(10/100) = 36 degrees"); // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie').length, 1, + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie').length, 1, "should have a pie chart"); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_pie_value').text(), + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_pie_value').text(), '10%', "should have 10% as pie value since int_field=10"); - assert.ok(_.str.include(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').first().attr('style'), + assert.ok(_.str.include(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').first().attr('style'), 'transform: rotate(180deg);'), "left mask should be covering the whole left side of the pie"); - assert.ok(_.str.include(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').last().attr('style'), + assert.ok(_.str.include(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').last().attr('style'), 'transform: rotate(36deg);'), "right mask should be rotated from 360*(10/100) = 36 degrees"); form.destroy(); @@ -2714,35 +2714,35 @@ QUnit.module('basic_fields', { res_id: 3, }); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie').length, 1, + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie').length, 1, "should have a pie chart"); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_pie_value').text(), + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_pie_value').text(), '80%', "should have 80% as pie value since int_field=80"); - assert.ok(_.str.include(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').first().attr('style'), + assert.ok(_.str.include(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').first().attr('style'), 'transform: rotate(288deg);'), "left mask should be rotated from 360*(80/100) = 288 degrees"); - assert.ok(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').last().hasClass('o_full'), + assert.ok(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').last().hasClass('o_full'), "right mask should be hidden since the value > 50%"); // switch to edit mode and check the result form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie').length, 1, + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie').length, 1, "should have a pie chart"); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_pie_value').text(), + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_pie_value').text(), '80%', "should have 80% as pie value since int_field=80"); - assert.ok(_.str.include(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').first().attr('style'), + assert.ok(_.str.include(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').first().attr('style'), 'transform: rotate(288deg);'), "left mask should be rotated from 360*(80/100) = 288 degrees"); - assert.ok(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').last().hasClass('o_full'), + assert.ok(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').last().hasClass('o_full'), "right mask should be hidden since the value > 50%"); // save form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie').length, 1, + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie').length, 1, "should have a pie chart"); - assert.strictEqual(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_pie_value').text(), + assert.strictEqual(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_pie_value').text(), '80%', "should have 80% as pie value since int_field=80"); - assert.ok(_.str.include(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').first().attr('style'), + assert.ok(_.str.include(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').first().attr('style'), 'transform: rotate(288deg);'), "left mask should be rotated from 360*(80/100) = 288 degrees"); - assert.ok(form.$('.o_form_field_percent_pie.o_form_field .o_pie .o_mask').last().hasClass('o_full'), + assert.ok(form.$('.o_field_percent_pie.o_field_widget .o_pie .o_mask').last().hasClass('o_full'), "right mask should be hidden since the value > 50%"); form.destroy(); @@ -2767,31 +2767,31 @@ QUnit.module('basic_fields', { // '</tree>', // }); // - // assert.strictEqual(list.$('.o_form_field_percent_pie .o_pie').length, 5, + // assert.strictEqual(list.$('.o_field_percent_pie .o_pie').length, 5, // "should have five pie charts"); - // assert.strictEqual(list.$('.o_form_field_percent_pie:first .o_pie .o_pie_value').first().text(), + // assert.strictEqual(list.$('.o_field_percent_pie:first .o_pie .o_pie_value').first().text(), // '10%', "should have 10% as pie value since int_field=10"); - // assert.strictEqual(list.$('.o_form_field_percent_pie:first .o_pie .o_mask').first().attr('style'), + // assert.strictEqual(list.$('.o_field_percent_pie:first .o_pie .o_mask').first().attr('style'), // 'transform: rotate(180deg);', "left mask should be covering the whole left side of the pie"); - // assert.strictEqual(list.$('.o_form_field_percent_pie:first .o_pie .o_mask').last().attr('style'), + // assert.strictEqual(list.$('.o_field_percent_pie:first .o_pie .o_mask').last().attr('style'), // 'transform: rotate(36deg);', "right mask should be rotated from 360*(10/100) = 36 degrees"); // // // switch to edit mode and check the result // list.$('tbody td:not(.o_list_record_selector)').first().click(); - // assert.strictEqual(list.$('.o_form_field_percent_pie:first .o_pie .o_pie_value').first().text(), + // assert.strictEqual(list.$('.o_field_percent_pie:first .o_pie .o_pie_value').first().text(), // '10%', "should have 10% as pie value since int_field=10"); - // assert.strictEqual(list.$('.o_form_field_percent_pie:first .o_pie .o_mask').first().attr('style'), + // assert.strictEqual(list.$('.o_field_percent_pie:first .o_pie .o_mask').first().attr('style'), // 'transform: rotate(180deg);', "left mask should be covering the whole right side of the pie"); - // assert.strictEqual(list.$('.o_form_field_percent_pie:first .o_pie .o_mask').last().attr('style'), + // assert.strictEqual(list.$('.o_field_percent_pie:first .o_pie .o_mask').last().attr('style'), // 'transform: rotate(36deg);', "right mask should be rotated from 360*(10/100) = 36 degrees"); // // // save // list.$buttons.find('.o_list_button_save').click(); - // assert.strictEqual(list.$('.o_form_field_percent_pie:first .o_pie .o_pie_value').first().text(), + // assert.strictEqual(list.$('.o_field_percent_pie:first .o_pie .o_pie_value').first().text(), // '10%', "should have 10% as pie value since int_field=10"); - // assert.strictEqual(list.$('.o_form_field_percent_pie:first .o_pie .o_mask').first().attr('style'), + // assert.strictEqual(list.$('.o_field_percent_pie:first .o_pie .o_mask').first().attr('style'), // 'transform: rotate(180deg);', "left mask should be covering the whole right side of the pie"); - // assert.strictEqual(list.$('.o_form_field_percent_pie:first .o_pie .o_mask').last().attr('style'), + // assert.strictEqual(list.$('.o_field_percent_pie:first .o_pie .o_mask').last().attr('style'), // 'transform: rotate(36deg);', "right mask should be rotated from 360*(10/100) = 36 degrees"); // // list.destroy(); @@ -2823,7 +2823,7 @@ QUnit.module('basic_fields', { // As the domain is empty, there should be a button to add the first // domain part - var $domain = form.$(".o_form_field_domain"); + var $domain = form.$(".o_field_domain"); var $domainAddFirstNodeButton = $domain.find(".o_domain_add_first_node_button"); assert.equal($domainAddFirstNodeButton.length, 1, "there should be a button to create first domain element"); @@ -2865,7 +2865,7 @@ QUnit.module('basic_fields', { // Saving the form view should show a readonly domain containing the // "color" field form.$buttons.find('.o_form_button_save').click(); - $domain = form.$(".o_form_field_domain"); + $domain = form.$(".o_field_domain"); assert.ok($domain.html().indexOf("Color index") >= 0, "field selector readonly value should now contain 'Color index'"); form.destroy(); @@ -2897,7 +2897,7 @@ QUnit.module('basic_fields', { // As the domain is equal to [["id", "=", 1]] there should be a field // selector to change this - var $domain = form.$(".o_form_field_domain"); + var $domain = form.$(".o_field_domain"); var $fieldSelector = $domain.find(".o_field_selector"); assert.equal($fieldSelector.length, 1, "there should be a field selector"); @@ -2924,7 +2924,7 @@ QUnit.module('basic_fields', { "field selector popover should contain 'Product Name' field"); // Now change the value of the "bar" field to "partner_type" - form.$(".o_field_widget.o_form_input").click().val("partner_type").trigger("input"); + form.$("input.o_field_widget").click().val("partner_type").trigger("input"); // Refocusing the field selector input should open the popover again $fieldSelector = form.$(".o_field_selector"); diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index d6ea4a946be..db81e19731c 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -259,9 +259,9 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget'); + var $dropdown = form.$('.o_field_many2one input').autocomplete('widget'); - form.$('.o_form_field_many2one input').click(); + form.$('.o_field_many2one input').click(); assert.ok($dropdown.is(':visible'), 'clicking on the m2o input should open the dropdown if it is not open yet'); assert.strictEqual($dropdown.find('li:not(.o_m2o_dropdown_option)').length, 7, @@ -269,19 +269,19 @@ QUnit.module('relational_fields', { assert.strictEqual($dropdown.find('li.o_m2o_dropdown_option').length, 2, 'autocomplete should contain "Search More" and Create and Edit..."'); - form.$('.o_form_field_many2one input').click(); + form.$('.o_field_many2one input').click(); assert.ok(!$dropdown.is(':visible'), 'clicking on the m2o input should close the dropdown if it is open'); // change the value of the m2o with a suggestion of the dropdown - form.$('.o_form_field_many2one input').click(); + form.$('.o_field_many2one input').click(); $dropdown.find('li:first()').click(); assert.ok(!$dropdown.is(':visible'), 'clicking on a value should close the dropdown'); - assert.strictEqual(form.$('.o_form_field_many2one input').val(), 'first record', + assert.strictEqual(form.$('.o_field_many2one input').val(), 'first record', 'value of the m2o should have been correctly updated'); // change the value of the m2o with a record in the 'Search More' modal - form.$('.o_form_field_many2one input').click(); + form.$('.o_field_many2one input').click(); // click on 'Search More' (mouseenter required by ui-autocomplete) $dropdown.find('.o_m2o_dropdown_option:contains(Search)').mouseenter().click(); assert.ok($('.modal .o_list_view').length, "should have opened a list view in a modal"); @@ -299,7 +299,7 @@ QUnit.module('relational_fields', { $('.modal tbody tr:contains(Partner 20)').click(); // choose record 'Partner 20' assert.ok(!$('.modal').length, "should have closed the modal"); assert.ok(!$dropdown.is(':visible'), 'should have closed the dropdown'); - assert.strictEqual(form.$('.o_form_field_many2one input').val(), 'Partner 20', + assert.strictEqual(form.$('.o_field_many2one input').val(), 'Partner 20', 'value of the m2o should have been correctly updated'); // save @@ -479,8 +479,8 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('a').text(), '', 'the tag a should be empty'); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_many2one input').click(); - form.$('.o_form_field_many2one input').autocomplete('widget').find('a').first().click(); + form.$('.o_field_many2one input').click(); + form.$('.o_field_many2one input').autocomplete('widget').find('a').first().click(); assert.strictEqual(form.$('input').val(), "xphone", "should have selected xphone"); @@ -549,8 +549,8 @@ QUnit.module('relational_fields', { }, }); - form.$('.o_form_field_many2one input').focus(); - form.$('.o_form_field_many2one input').val('new partner').trigger('keyup').trigger('focusout'); + form.$('.o_field_many2one input').focus(); + form.$('.o_field_many2one input').val('new partner').trigger('keyup').trigger('focusout'); $('.modal .modal-footer .btn-primary').first().click(); @@ -571,8 +571,8 @@ QUnit.module('relational_fields', { '</form>', }); - form.$('.o_form_field_many2one input').focus(); - form.$('.o_form_field_many2one input').val('new partner').trigger('keyup').trigger('focusout'); + form.$('.o_field_many2one input').focus(); + form.$('.o_field_many2one input').val('new partner').trigger('keyup').trigger('focusout'); assert.strictEqual($('.modal').length, 0, "should not display the create modal"); form.destroy(); @@ -607,17 +607,17 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('td.o_list_record_selector').length, 0, "embedded one2many should not have a selector"); - assert.ok(!form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(!form.$('.o_field_x2many_list_row_add').length, "embedded one2many should not be editable"); assert.ok(!form.$('td.o_list_record_delete').length, "embedded one2many records should not have a trash icon"); form.$buttons.find('.o_form_button_edit').click(); - assert.ok(form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(form.$('.o_field_x2many_list_row_add').length, "embedded one2many should now be editable"); - assert.strictEqual(form.$('.o_form_field_x2many_list_row_add').attr('colspan'), "2", + assert.strictEqual(form.$('.o_field_x2many_list_row_add').attr('colspan'), "2", "should have colspan 2 (one for field foo, one for being below trash icon)"); assert.ok(form.$('td.o_list_record_delete').length, @@ -934,12 +934,12 @@ QUnit.module('relational_fields', { res_id: 1, }); - assert.ok(!form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(!form.$('.o_field_x2many_list_row_add').length, '"Add an item" link should not be available in readonly'); form.$buttons.find('.o_form_button_edit').click(); - assert.ok(!form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(!form.$('.o_field_x2many_list_row_add').length, '"Add an item" link should not be available in readonly'); form.destroy(); }); @@ -1027,7 +1027,7 @@ QUnit.module('relational_fields', { assert.ok(!form.$('.o_kanban_view .delete_icon').length, 'delete icon should not be visible in readonly'); - assert.ok(!form.$('.o_form_field_one2many .o-kanban-button-new').length, + assert.ok(!form.$('.o_field_one2many .o-kanban-button-new').length, '"Create" button should not be visible in readonly'); form.$buttons.find('.o_form_button_edit').click(); @@ -1040,20 +1040,20 @@ QUnit.module('relational_fields', { 'color of subrecord should be the one in DB'); assert.ok(form.$('.o_kanban_view .delete_icon').length, 'delete icon should be visible in edit'); - assert.ok(form.$('.o_form_field_one2many .o-kanban-button-new').length, + assert.ok(form.$('.o_field_one2many .o-kanban-button-new').length, '"Create" button should be visible in edit'); // edit existing subrecord form.$('.oe_kanban_global_click').click(); - $('.modal .o_form_view .o_form_input').val('new name').trigger('input'); + $('.modal .o_form_view input').val('new name').trigger('input'); $('.modal .modal-footer .btn-primary').click(); // save assert.strictEqual(form.$('.o_kanban_record span:first').text(), 'new name', 'value of subrecord should have been updated'); // create a new subrecord form.$('.o-kanban-button-new').click(); - $('.modal .o_form_view .o_form_input').val('new subrecord 1').trigger('input'); + $('.modal .o_form_view input').val('new subrecord 1').trigger('input'); $('.modal .modal-footer .btn-primary').click(); // save and close assert.strictEqual(form.$('.o_kanban_record:not(.o_kanban_ghost)').length, 2, 'should contain 2 records'); @@ -1062,9 +1062,9 @@ QUnit.module('relational_fields', { // create two new subrecords form.$('.o-kanban-button-new').click(); - $('.modal .o_form_view .o_form_input').val('new subrecord 2').trigger('input'); + $('.modal .o_form_view input').val('new subrecord 2').trigger('input'); $('.modal .modal-footer .btn-primary:nth(1)').click(); // save and new - $('.modal .o_form_view .o_form_input').val('new subrecord 3').trigger('input'); + $('.modal .o_form_view input').val('new subrecord 3').trigger('input'); $('.modal .modal-footer .btn-primary').click(); // save and close assert.strictEqual(form.$('.o_kanban_record:not(.o_kanban_ghost)').length, 4, 'should contain 4 records'); @@ -1153,7 +1153,7 @@ QUnit.module('relational_fields', { assert.ok(!form.$('.o_list_record_delete').length, 'delete icon should not be visible in readonly'); - assert.ok(!form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(!form.$('.o_field_x2many_list_row_add').length, '"Add an item" should not be visible in readonly'); form.$buttons.find('.o_form_button_edit').click(); @@ -1164,13 +1164,13 @@ QUnit.module('relational_fields', { 'display_name of first subrecord should be the one in DB'); assert.ok(form.$('.o_list_record_delete').length, 'delete icon should be visible in edit'); - assert.ok(form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(form.$('.o_field_x2many_list_row_add').length, '"Add an item" should not visible in edit'); // edit existing subrecord form.$('.o_list_view tbody tr:first() td:eq(1)').click(); - $('.modal .o_form_view .o_form_input').val('new name').trigger('input'); + $('.modal .o_form_view input').val('new name').trigger('input'); $('.modal .modal-footer .btn-primary').click(); // save assert.strictEqual(form.$('.o_list_view tbody td:first()').text(), 'new name', 'value of subrecord should have been updated'); @@ -1213,7 +1213,7 @@ QUnit.module('relational_fields', { res_id: 1, }); - assert.ok(!form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(!form.$('.o_field_x2many_list_row_add').length, '"Add an item" link should not be available in readonly'); form.$('.o_list_view tbody td:first()').click(); @@ -1223,7 +1223,7 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_edit').click(); - assert.ok(form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(form.$('.o_field_x2many_list_row_add').length, '"Add an item" link should be available in edit'); // edit existing subrecord @@ -1232,7 +1232,7 @@ QUnit.module('relational_fields', { 'in edit, clicking on a subrecord should not open a dialog'); assert.ok(form.$('.o_list_view tbody tr:first()').hasClass('o_selected_row'), 'first row should be in edition'); - form.$('.o_list_view .o_form_input:first()').val('new name').trigger('input'); + form.$('.o_list_view input:first()').val('new name').trigger('input'); form.$('.o_list_view tbody tr:nth(1) td:first').click(); // click on second record to validate the first one assert.ok(!form.$('.o_list_view tbody tr:first').hasClass('o_selected_row'), @@ -1273,11 +1273,11 @@ QUnit.module('relational_fields', { // edit mode, then click on Add an item and enter a value form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); form.$('.o_selected_row > td input').val('kartoffel').trigger('input'); // click again on Add an item - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); assert.strictEqual(form.$('td:contains(kartoffel)').length, 1, "should have one td with the new value"); assert.strictEqual(form.$('.o_selected_row > td input').length, 1, @@ -1319,8 +1319,8 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('tr.o_data_row').length, 1, "should have 1 data rows"); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); assert.strictEqual(form.$('tr.o_data_row').length, 3, "should have 3 data rows"); @@ -1365,14 +1365,14 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('tr.o_data_row').length, 0, "should have 0 data rows"); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); assert.strictEqual(form.$('textarea').val(), "", "field turtle_description should be empty"); // add a value in the turtle_trululu field to trigger an onchange - var $dropdown = form.$('.o_form_field_many2one[name=turtle_trululu] input') + var $dropdown = form.$('.o_field_many2one[name=turtle_trululu] input') .autocomplete('widget'); - form.$('.o_form_field_many2one[name=turtle_trululu] input').click(); + form.$('.o_field_many2one[name=turtle_trululu] input').click(); $dropdown.find('a:contains(first record)').mouseenter().click(); assert.strictEqual(form.$('textarea').val(), "Some Description", "field turtle_description should be set to the result of the onchange"); @@ -1411,13 +1411,13 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('tr.o_data_row').length, 0, "should have 0 data rows"); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); form.$('label.o_form_label').first().click(); assert.strictEqual(form.$('tr.o_data_row').length, 0, "should still have 0 data rows"); // click on Add an item again, then click on save - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); form.$buttons.find('.o_form_button_save').click(); assert.strictEqual(form.$('tr.o_data_row').length, 0, "should still have 0 data rows"); @@ -1453,7 +1453,7 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('tr.o_data_row').length, 0, "should have 0 data rows"); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); assert.strictEqual(form.$('tr.o_data_row').length, 1, "should have 1 data rows"); @@ -1518,7 +1518,7 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('tr.o_data_row').length, 0, "should have 0 data rows"); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); // input some text in required turtle_foo field form.$('input[name="turtle_foo"]').val('aubergine').trigger('input'); @@ -1718,10 +1718,10 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_edit').click(); - assert.ok(form.$('.o_list_view tbody tr:eq(0) td:first').hasClass('o_readonly'), + assert.ok(form.$('.o_list_view tbody tr:eq(0) td:first').hasClass('o_readonly_modifier'), "first record should have display_name in readonly mode"); - assert.notOk(form.$('.o_list_view tbody tr:eq(1) td:first').hasClass('o_readonly'), + assert.notOk(form.$('.o_list_view tbody tr:eq(1) td:first').hasClass('o_readonly_modifier'), "second record should not have display_name in readonly mode"); form.destroy(); }); @@ -1752,8 +1752,8 @@ QUnit.module('relational_fields', { 'o2m pager should be hidden'); // click to create a subrecord - form.$('tbody td.o_form_field_x2many_list_row_add a').click(); - $('.modal .o_form_input').val('new record').trigger('input'); + form.$('tbody td.o_field_x2many_list_row_add a').click(); + $('.modal input').val('new record').trigger('input'); $('.modal .modal-footer button:eq(0)').click(); // save and close assert.ok(!form.$('.o_x2m_control_panel .o_cp_pager div').is(':visible'), @@ -1807,11 +1807,11 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_edit').click(); - form.$('tbody td.o_form_field_x2many_list_row_add a').click(); + form.$('tbody td.o_field_x2many_list_row_add a').click(); - $('.modal .o_form_field_many2one input').click(); + $('.modal .o_field_many2one input').click(); - var $dropdown = $('.modal .o_form_field_many2one input').autocomplete('widget'); + var $dropdown = $('.modal .o_field_many2one input').autocomplete('widget'); $dropdown.find('li:eq(1) a').mouseenter(); $dropdown.find('li:eq(1) a').click(); @@ -1865,11 +1865,11 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_edit').click(); - form.$('tbody td.o_form_field_x2many_list_row_add a').click(); + form.$('tbody td.o_field_x2many_list_row_add a').click(); // write in the many2one field, value = 37 (xphone) - $('.modal .o_form_field_many2one input').click(); - var $dropdown = $('.modal .o_form_field_many2one input').autocomplete('widget'); + $('.modal .o_field_many2one input').click(); + var $dropdown = $('.modal .o_field_many2one input').autocomplete('widget'); $dropdown.find('li:eq(0) a').mouseenter(); $dropdown.find('li:eq(0) a').click(); @@ -1900,8 +1900,8 @@ QUnit.module('relational_fields', { "should display 123 (previous change has been discarded)"); // write in the many2one field, value = 41 (xpad) - $('.modal .o_form_field_many2one input').click(); - $dropdown = $('.modal .o_form_field_many2one input').autocomplete('widget'); + $('.modal .o_field_many2one input').click(); + $dropdown = $('.modal .o_field_many2one input').autocomplete('widget'); $dropdown.find('li:eq(1) a').mouseenter(); $dropdown.find('li:eq(1) a').click(); @@ -1956,7 +1956,7 @@ QUnit.module('relational_fields', { form.$('tr.o_data_row:eq(0) td:contains(xphone)').click(); // write in the many2one field - $('.modal .o_form_field_many2one input').click(); + $('.modal .o_field_many2one input').click(); form.destroy(); }); @@ -1994,7 +1994,7 @@ QUnit.module('relational_fields', { form.$('tr.o_data_row:eq(0) td:contains(xphone)').click(); // trigger a name search - form.$('table td input.o_form_input').click(); + form.$('table td input').click(); form.destroy(); }); @@ -2030,7 +2030,7 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); form.destroy(); }); @@ -2055,17 +2055,17 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('tbody td.o_form_field_x2many_list_row_add a').click(); + form.$('tbody td.o_field_x2many_list_row_add a').click(); - assert.strictEqual(form.$('td input.o_field_widget.o_form_input').length, 1, + assert.strictEqual(form.$('td input.o_field_widget').length, 1, "should have created a row in edit mode"); - form.$('td input.o_field_widget.o_form_input').val('a').trigger('input'); + form.$('td input.o_field_widget').val('a').trigger('input'); - assert.strictEqual(form.$('td input.o_field_widget.o_form_input').length, 1, + assert.strictEqual(form.$('td input.o_field_widget').length, 1, "should not have unselected the row after edition"); - form.$('td input.o_field_widget.o_form_input').val('abc').trigger('input'); + form.$('td input.o_field_widget').val('abc').trigger('input'); form.$buttons.find('.o_form_button_save').click(); assert.strictEqual(form.$('td:contains(abc)').length, 1, @@ -2100,7 +2100,7 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('tbody td.o_form_field_x2many_list_row_add a').click(); + form.$('tbody td.o_field_x2many_list_row_add a').click(); form.destroy(); }); @@ -2148,7 +2148,7 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); assert.strictEqual($('.modal .o_data_row').length, 2, "sould have 2 records in the select view (the last one is not displayed because it is already selected)"); @@ -2157,14 +2157,14 @@ QUnit.module('relational_fields', { $('.modal .o_select_button').click(); $('.o_form_button_save').click(); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); assert.strictEqual($('.modal .o_data_row').length, 1, "sould have 1 record in the select view"); $('.modal-footer button:eq(1)').click(); - $('.modal input.o_form_field[name="turtle_foo"]').val('tototo').trigger('input'); - $('.modal input.o_form_field[name="turtle_int"]').val(50).trigger('input'); + $('.modal input.o_field_widget[name="turtle_foo"]').val('tototo').trigger('input'); + $('.modal input.o_field_widget[name="turtle_int"]').val(50).trigger('input'); var $many2one = $('.modal [name="product_id"] input').click(); var $dropdown = $many2one.autocomplete('widget'); $dropdown.find('li:first a').mouseenter(); @@ -2245,7 +2245,7 @@ QUnit.module('relational_fields', { // add a one2many record form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); $('.modal .o_data_row:first .o_list_record_selector input').click(); $('.modal .o_select_button').click(); @@ -2294,7 +2294,7 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('tbody td.o_form_field_x2many_list_row_add a').click(); + form.$('tbody td.o_field_x2many_list_row_add a').click(); form.destroy(); }); @@ -2326,7 +2326,7 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('tbody td.o_form_field_x2many_list_row_add a').click(); + form.$('tbody td.o_field_x2many_list_row_add a').click(); form.destroy(); }); @@ -2357,7 +2357,7 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('tbody td.o_form_field_x2many_list_row_add a').click(); + form.$('tbody td.o_field_x2many_list_row_add a').click(); form.destroy(); }); @@ -2384,11 +2384,11 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('tbody td.o_form_field_x2many_list_row_add a').click(); + form.$('tbody td.o_field_x2many_list_row_add a').click(); $('.modal-footer button.btn-primary').first().click(); assert.strictEqual($('.modal').length, 1, "should still have an open modal"); - assert.strictEqual($('.modal tbody label.o_form_invalid').length, 1, + assert.strictEqual($('.modal tbody label.o_field_invalid').length, 1, "should have displayed invalid fields"); form.destroy(); }); @@ -2539,7 +2539,7 @@ QUnit.module('relational_fields', { } }); - assert.strictEqual(form.$('.o_form_field[name="turtles"] .o_list_view').length, 1, + assert.strictEqual(form.$('.o_field_widget[name="turtles"] .o_list_view').length, 1, 'should display one2many list view in the modal'); assert.strictEqual(form.$('.o_data_row').length, 2, @@ -2603,7 +2603,7 @@ QUnit.module('relational_fields', { form.$('.o_data_row:first').click(); - assert.strictEqual($('.modal .o_form_field').text(), "xphone", + assert.strictEqual($('.modal .o_field_widget').text(), "xphone", 'should display the form view dialog with the many2one value'); $('.modal-footer button').click(); // close the modal @@ -2612,21 +2612,21 @@ QUnit.module('relational_fields', { // edit the m2m of first row form.$('.o_list_view tbody td:first()').click(); // remove a tag - form.$('.o_form_field_many2manytags .badge:contains(aaa) .o_delete').click(); - assert.strictEqual(form.$('.o_selected_row .o_form_field_many2manytags .o_badge_text:contains(aaa)').length, 0, + form.$('.o_field_many2manytags .badge:contains(aaa) .o_delete').click(); + assert.strictEqual(form.$('.o_selected_row .o_field_many2manytags .o_badge_text:contains(aaa)').length, 0, "tag should have been correctly removed"); // add a tag - var $m2mInput = form.$('.o_selected_row .o_form_field_many2manytags input'); + var $m2mInput = form.$('.o_selected_row .o_field_many2manytags input'); $m2mInput.click(); $m2mInput.autocomplete('widget').find('li:first()').click(); - assert.strictEqual(form.$('.o_selected_row .o_form_field_many2manytags .o_badge_text:contains(first record)').length, 1, + assert.strictEqual(form.$('.o_selected_row .o_field_many2manytags .o_badge_text:contains(first record)').length, 1, "tag should have been correctly added"); // edit the m2o of first row - var $m2oInput = form.$('.o_selected_row .o_form_field_many2one:first input'); + var $m2oInput = form.$('.o_selected_row .o_field_many2one:first input'); $m2oInput.click(); $m2oInput.autocomplete('widget').find('li:contains(xpad)').mouseover().click(); - assert.strictEqual(form.$('.o_selected_row .o_form_field_many2one:first input').val(), 'xpad', + assert.strictEqual(form.$('.o_selected_row .o_field_many2one:first input').val(), 'xpad', "m2o value should have been updated"); // save (should correctly generate the commands) @@ -2673,7 +2673,7 @@ QUnit.module('relational_fields', { form.$('.o_data_row:first').click(); - assert.strictEqual($('.modal .o_form_field[name="partner_ids"] .o_list_view').length, 1, + assert.strictEqual($('.modal .o_field_widget[name="partner_ids"] .o_list_view').length, 1, 'should display many2many list view in the modal'); form.destroy(); @@ -2705,7 +2705,7 @@ QUnit.module('relational_fields', { form.$('.o_data_row:first').click(); - assert.strictEqual($('.modal .o_form_field[name="turtle_foo"]').text(), 'blip', + assert.strictEqual($('.modal .o_field_widget[name="turtle_foo"]').text(), 'blip', 'should open the modal and display the form field'); form.destroy(); @@ -2737,7 +2737,7 @@ QUnit.module('relational_fields', { form.$('.o_data_row:first').click(); - assert.strictEqual($('.modal .o_form_field[name="turtle_foo"]').text(), 'blip', + assert.strictEqual($('.modal .o_field_widget[name="turtle_foo"]').text(), 'blip', 'should open the modal and display the form field'); form.destroy(); @@ -2784,38 +2784,38 @@ QUnit.module('relational_fields', { res_id: 4, }); - assert.strictEqual(form.$('.o_form_field .o_kanban_view').length, 1, + assert.strictEqual(form.$('.o_field_widget .o_kanban_view').length, 1, "should have one inner kanban view for the one2many field"); - assert.strictEqual(form.$('.o_form_field .o_kanban_view .o_kanban_record:not(.o_kanban_ghost)').length, 0, + assert.strictEqual(form.$('.o_field_widget .o_kanban_view .o_kanban_record:not(.o_kanban_ghost)').length, 0, "should not have kanban records yet"); // // switch to edit mode and create a new kanban record form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field .o-kanban-button-new').click(); + form.$('.o_field_widget .o-kanban-button-new').click(); // save & close the modal - assert.strictEqual($('.modal-content input.o_form_field').val(), 'My little Foo Value', + assert.strictEqual($('.modal-content input.o_field_widget').val(), 'My little Foo Value', "should already have the default value for field foo"); $('.modal-content .btn-primary').first().click(); - assert.strictEqual(form.$('.o_form_field .o_kanban_view').length, 1, + assert.strictEqual(form.$('.o_field_widget .o_kanban_view').length, 1, "should have one inner kanban view for the one2many field"); - assert.strictEqual(form.$('.o_form_field .o_kanban_view .o_kanban_record:not(.o_kanban_ghost)').length, 1, + assert.strictEqual(form.$('.o_field_widget .o_kanban_view .o_kanban_record:not(.o_kanban_ghost)').length, 1, "should now have one kanban record"); - assert.strictEqual(form.$('.o_form_field .o_kanban_view .o_kanban_record:not(.o_kanban_ghost) .o_test_id').text(), + assert.strictEqual(form.$('.o_field_widget .o_kanban_view .o_kanban_record:not(.o_kanban_ghost) .o_test_id').text(), '', "should not have a value for the id field"); - assert.strictEqual(form.$('.o_form_field .o_kanban_view .o_kanban_record:not(.o_kanban_ghost) .o_test_foo').text(), + assert.strictEqual(form.$('.o_field_widget .o_kanban_view .o_kanban_record:not(.o_kanban_ghost) .o_test_foo').text(), 'My little Foo Value', "should have a value for the foo field"); // save the view to force a create of the new record in the one2many form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field .o_kanban_view').length, 1, + assert.strictEqual(form.$('.o_field_widget .o_kanban_view').length, 1, "should have one inner kanban view for the one2many field"); - assert.strictEqual(form.$('.o_form_field .o_kanban_view .o_kanban_record:not(.o_kanban_ghost)').length, 1, + assert.strictEqual(form.$('.o_field_widget .o_kanban_view .o_kanban_record:not(.o_kanban_ghost)').length, 1, "should now have one kanban record"); - assert.notEqual(form.$('.o_form_field .o_kanban_view .o_kanban_record:not(.o_kanban_ghost) .o_test_id').text(), + assert.notEqual(form.$('.o_field_widget .o_kanban_view .o_kanban_record:not(.o_kanban_ghost) .o_test_id').text(), '', "should now have a value for the id field"); - assert.strictEqual(form.$('.o_form_field .o_kanban_view .o_kanban_record:not(.o_kanban_ghost) .o_test_foo').text(), + assert.strictEqual(form.$('.o_field_widget .o_kanban_view .o_kanban_record:not(.o_kanban_ghost) .o_test_foo').text(), 'My little Foo Value', "should still have a value for the foo field"); form.destroy(); @@ -2844,11 +2844,11 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_edit').click(); form.$('.o_data_row:first td:first').click(); - assert.strictEqual(form.$('.o_form_input[name="turtle_foo"]')[0], document.activeElement, + assert.strictEqual(form.$('input[name="turtle_foo"]')[0], document.activeElement, "turtle foo field should have focus"); - form.$('.o_form_input[name="turtle_foo"]').trigger({type: 'keydown', which: $.ui.keyCode.TAB}); - assert.strictEqual(form.$('.o_form_input[name="turtle_int"]')[0], document.activeElement, + form.$('input[name="turtle_foo"]').trigger({type: 'keydown', which: $.ui.keyCode.TAB}); + assert.strictEqual(form.$('input[name="turtle_int"]')[0], document.activeElement, "turtle int field should have focus"); form.destroy(); }); @@ -2887,7 +2887,7 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('.o_data_row').length, 1, "should start with one data row"); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); assert.strictEqual(form.$('.o_data_row').length, 2, "should have 2 data rows"); @@ -2934,7 +2934,7 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('.o_data_row').length, 1, "should start with one data row"); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); assert.strictEqual(form.$('.o_data_row').length, 2, "should have 2 data rows"); @@ -2975,7 +2975,7 @@ QUnit.module('relational_fields', { res_id: 1, }); - assert.strictEqual(form.$('.o_form_field_one2many .o_kanban_view').length, 1, + assert.strictEqual(form.$('.o_field_one2many .o_kanban_view').length, 1, "should have rendered a kanban view"); form.destroy(); @@ -3014,16 +3014,16 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field[name="int_field"]').val(), "0", + assert.strictEqual(form.$('.o_field_widget[name="int_field"]').val(), "0", "int_field should start with value 0"); - form.$('.o_form_field_x2many_list_row_add a').click(); - assert.strictEqual(form.$('.o_form_field[name="int_field"]').val(), "0", + form.$('.o_field_x2many_list_row_add a').click(); + assert.strictEqual(form.$('.o_field_widget[name="int_field"]').val(), "0", "int_field should still be 0 (no onchange should have been done yet"); assert.verifySteps(['read', 'default_get'], "no onchange should have been applied"); form.$('.o_field_widget[name="turtle_foo"]').val("some text").trigger('input'); - assert.strictEqual(form.$('.o_form_field[name="int_field"]').val(), "1", + assert.strictEqual(form.$('.o_field_widget[name="int_field"]').val(), "1", "int_field should now be 1 (the onchange should have been done"); form.destroy(); @@ -3066,16 +3066,16 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field[name="int_field"]').val(), "0", + assert.strictEqual(form.$('.o_field_widget[name="int_field"]').val(), "0", "int_field should start with value 0"); - form.$('.o_form_field_x2many_list_row_add a').click(); - assert.strictEqual(form.$('.o_form_field[name="int_field"]').val(), "0", + form.$('.o_field_x2many_list_row_add a').click(); + assert.strictEqual(form.$('.o_field_widget[name="int_field"]').val(), "0", "int_field should still be 0 (no onchange should have been done yet"); assert.verifySteps(['read', 'default_get'], "no onchange should have been applied"); form.$('.o_field_widget[name="turtle_foo"]').val("some text").trigger('input'); - assert.strictEqual(form.$('.o_form_field[name="int_field"]').val(), "1", + assert.strictEqual(form.$('.o_field_widget[name="int_field"]').val(), "1", "int_field should now be 1 (the onchange should have been done"); form.destroy(); @@ -3152,7 +3152,7 @@ QUnit.module('relational_fields', { assert.ok(!form.$('.o_kanban_view .delete_icon').length, 'delete icon should not be visible in readonly'); - assert.ok(!form.$('.o_form_field_many2many .o-kanban-button-new').length, + assert.ok(!form.$('.o_field_many2many .o-kanban-button-new').length, '"Add" button should not be visible in readonly'); form.$buttons.find('.o_form_button_edit').click(); @@ -3163,20 +3163,20 @@ QUnit.module('relational_fields', { 'display_name of subrecord should be the one in DB'); assert.ok(form.$('.o_kanban_view .delete_icon').length, 'delete icon should be visible in edit'); - assert.ok(form.$('.o_form_field_many2many .o-kanban-button-new').length, + assert.ok(form.$('.o_field_many2many .o-kanban-button-new').length, '"Add" button should be visible in edit'); // edit existing subrecord form.$('.oe_kanban_global_click:first()').click(); - $('.modal .o_form_view .o_form_input').val('new name').trigger('input'); + $('.modal .o_form_view input').val('new name').trigger('input'); $('.modal .modal-footer .btn-primary').click(); // save assert.strictEqual(form.$('.o_kanban_record:first() span').text(), 'new name', 'value of subrecord should have been updated'); // add subrecords // -> single select - form.$('.o_form_field_many2many .o-kanban-button-new').click(); + form.$('.o_field_many2many .o-kanban-button-new').click(); assert.ok($('.modal .o_list_view').length, "should have opened a list view in a modal"); assert.strictEqual($('.modal .o_list_view tbody .o_list_record_selector').length, 3, "list view should contain 3 records"); @@ -3188,7 +3188,7 @@ QUnit.module('relational_fields', { 'record "red" should be in the kanban'); // -> multiple select - form.$('.o_form_field_many2many .o-kanban-button-new').click(); + form.$('.o_field_many2many .o-kanban-button-new').click(); assert.ok($('.modal .o_select_button').prop('disabled'), "select button should be disabled"); assert.strictEqual($('.modal .o_list_view tbody .o_list_record_selector').length, 2, "list view should contain 2 records"); @@ -3199,7 +3199,7 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('.o_kanban_record:not(.o_kanban_ghost)').length, 5, 'kanban should now contain 5 records'); // -> created record - form.$('.o_form_field_many2many .o-kanban-button-new').click(); + form.$('.o_field_many2many .o-kanban-button-new').click(); $('.modal .modal-footer .btn-primary:nth(1)').click(); // click on 'Create' assert.ok($('.modal .o_form_view.o_form_editable').length, "should have opened a form view in edit mode, in a modal"); @@ -3297,7 +3297,7 @@ QUnit.module('relational_fields', { assert.ok(!form.$('.o_list_record_delete').length, 'delete icon should not be visible in readonly'); - assert.ok(!form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(!form.$('.o_field_x2many_list_row_add').length, '"Add an item" should not be visible in readonly'); form.$buttons.find('.o_form_button_edit').click(); @@ -3308,13 +3308,13 @@ QUnit.module('relational_fields', { 'display_name of first subrecord should be the one in DB'); assert.ok(form.$('.o_list_record_delete').length, 'delete icon should be visible in edit'); - assert.ok(form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(form.$('.o_field_x2many_list_row_add').length, '"Add an item" should be visible in edit'); // edit existing subrecord form.$('.o_list_view tbody tr:first()').click(); - $('.modal .o_form_view .o_form_input').val('new name').trigger('input'); + $('.modal .o_form_view input').val('new name').trigger('input'); $('.modal .modal-footer .btn-primary').click(); // save assert.strictEqual(form.$('.o_list_view tbody td:first()').text(), 'new name', 'value of subrecord should have been updated'); @@ -3355,7 +3355,7 @@ QUnit.module('relational_fields', { assert.ok(!form.$('.o_list_record_delete').length, 'delete icon should not be visible in readonly'); - assert.ok(!form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(!form.$('.o_field_x2many_list_row_add').length, '"Add an item" should not be visible in readonly'); form.$buttons.find('.o_form_button_edit').click(); @@ -3366,7 +3366,7 @@ QUnit.module('relational_fields', { 'display_name of first subrecord should be the one in DB'); assert.ok(form.$('.o_list_record_delete').length, 'delete icon should be visible in edit'); - assert.ok(form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(form.$('.o_field_x2many_list_row_add').length, '"Add an item" should not visible in edit'); // edit existing subrecord @@ -3375,7 +3375,7 @@ QUnit.module('relational_fields', { 'in edit, clicking on a subrecord should not open a dialog'); assert.ok(form.$('.o_list_view tbody tr:first()').hasClass('o_selected_row'), 'first row should be in edition'); - form.$('.o_list_view .o_form_input:first()').val('new name').trigger('input'); + form.$('.o_list_view input:first()').val('new name').trigger('input'); // FIXME: this doesn"t work for now as the x2many fields are reset on field changed // form.$('.o_list_view tbody td:nth(1)').click(); // click on second record to validate the first one // assert.ok(!form.$('.o_list_view tbody tr:first()').hasClass('o_selected_row'), @@ -3416,7 +3416,7 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field_x2many_list_row_add').length, 1, "should have the 'Add an item' link"); + assert.strictEqual(form.$('.o_field_x2many_list_row_add').length, 1, "should have the 'Add an item' link"); assert.strictEqual(form.$('.o_list_record_delete').length, 2, "should have the 'Add an item' link"); form.destroy(); @@ -3437,7 +3437,7 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field_x2many_list_row_add').length, 0, "should not have the 'Add an item' link"); + assert.strictEqual(form.$('.o_field_x2many_list_row_add').length, 0, "should not have the 'Add an item' link"); assert.strictEqual(form.$('.o_list_record_delete').length, 0, "should not have the 'Add an item' link"); form.destroy(); @@ -3459,12 +3459,12 @@ QUnit.module('relational_fields', { res_id: 1, }); - assert.ok(!form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(!form.$('.o_field_x2many_list_row_add').length, '"Add an item" link should not be available in readonly'); form.$buttons.find('.o_form_button_edit').click(); - assert.ok(!form.$('.o_form_field_x2many_list_row_add').length, + assert.ok(!form.$('.o_field_x2many_list_row_add').length, '"Add an item" link should not be available in edit either'); form.destroy(); @@ -3508,7 +3508,7 @@ QUnit.module('relational_fields', { }, }); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); $('.modal .o_data_row:first').click(); // add a first record to the relation assert.strictEqual(form.$('.o_data_row').length, 1, @@ -3516,7 +3516,7 @@ QUnit.module('relational_fields', { assert.strictEqual(form.$('.o_data_row:first .o_badge_text').text(), 'leonardodonatello', "inner m2m should have been fetched and correctly displayed"); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); $('.modal .o_data_row:first').click(); // add a second record to the relation assert.strictEqual(form.$('.o_data_row').length, 2, @@ -3658,8 +3658,8 @@ QUnit.module('relational_fields', { }, }); - assert.ok(form.$('.o_statusbar_status').hasClass('o_form_field_empty'), - 'statusbar widget should have class o_form_field_empty'); + assert.ok(form.$('.o_statusbar_status').hasClass('o_field_empty'), + 'statusbar widget should have class o_field_empty'); assert.strictEqual(form.$('.o_statusbar_status').children().length, 0, 'statusbar widget should be empty'); form.destroy(); @@ -3896,7 +3896,7 @@ QUnit.module('relational_fields', { return this._super.apply(this, arguments); }, }); - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 2, + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 2, "should contain 2 tags"); assert.ok(form.$('span:contains(gold)').length, 'should have fetched and rendered gold partner tag'); @@ -3907,33 +3907,33 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 2, + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 2, "should still contain 2 tags in edit mode"); assert.ok(form.$('.o_tag_color_2 .o_badge_text:contains(gold)').length, 'first tag should still contain "gold" and be color 2 in edit mode'); - assert.strictEqual(form.$('.o_form_field_many2manytags .o_delete').length, 2, + assert.strictEqual(form.$('.o_field_many2manytags .o_delete').length, 2, "tags should contain a delete button"); // add an other existing tag - var $input = form.$('.o_form_field_many2manytags input'); + var $input = form.$('.o_field_many2manytags input'); $input.click(); // opens the dropdown assert.strictEqual($input.autocomplete('widget').find('li').length, 1, "autocomplete dropdown should have 1 entry"); assert.strictEqual($input.autocomplete('widget').find('li a:contains("red")').length, 1, "autocomplete dropdown should contain 'red'"); $input.autocomplete('widget').find('li').click(); // add 'red' - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 3, + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 3, "should contain 3 tags"); - assert.ok(form.$('.o_form_field_many2manytags > span:contains("red")').length, + assert.ok(form.$('.o_field_many2manytags > span:contains("red")').length, "should contain newly added tag 'red'"); - assert.ok(form.$('.o_form_field_many2manytags > span[data-color=8]:contains("red")').length, + assert.ok(form.$('.o_field_many2manytags > span[data-color=8]:contains("red")').length, "should have fetched the color of added tag"); // remove tag with id 14 - form.$('.o_form_field_many2manytags span[data-id=14] .o_delete').click(); - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 2, + form.$('.o_field_many2manytags span[data-id=14] .o_delete').click(); + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 2, "should contain 2 tags"); - assert.ok(!form.$('.o_form_field_many2manytags > span:contains("silver")').length, + assert.ok(!form.$('.o_field_many2manytags > span:contains("silver")').length, "should not contain tag 'silver' anymore"); // save the record (should do the write RPC with the correct commands) @@ -3969,7 +3969,7 @@ QUnit.module('relational_fields', { return this._super.apply(this, arguments); } }); - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 1, + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 1, "should contain 1 tag"); assert.ok(form.$('span:contains(gold)').length, 'should have fetched and rendered gold partner tag'); @@ -3977,16 +3977,16 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_edit').click(); // add an other existing tag - var $input = form.$('.o_form_field_many2manytags input'); + var $input = form.$('.o_field_many2manytags input'); $input.click(); // opens the dropdown assert.strictEqual($input.autocomplete('widget').find('li').length, 1, "autocomplete dropdown should have 1 entry"); assert.strictEqual($input.autocomplete('widget').find('li a:contains("silver")').length, 1, "autocomplete dropdown should contain 'silver'"); $input.autocomplete('widget').find('li').click(); // add 'silver' - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 2, + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 2, "should contain 2 tags"); - assert.ok(form.$('.o_form_field_many2manytags > span:contains("silver")').length, + assert.ok(form.$('.o_field_many2manytags > span:contains("silver")').length, "should contain newly added tag 'silver'"); form.destroy(); @@ -4014,14 +4014,14 @@ QUnit.module('relational_fields', { }); assert.ok(form.$('.o_form_view').hasClass('o_form_editable'), "form should be in edit mode"); - var $input = form.$('.o_form_field_many2manytags input'); + var $input = form.$('.o_field_many2manytags input'); $input.click(); // opens the dropdown assert.strictEqual($input.autocomplete('widget').find('li').length, 3, "autocomplete dropdown should have 3 entries (2 values + 'Search and Edit...')"); $input.autocomplete('widget').find('li:first()').click(); // adds a tag - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 1, + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 1, "should contain 1 tag"); - assert.ok(form.$('.o_form_field_many2manytags > span:contains("gold")').length, + assert.ok(form.$('.o_field_many2manytags > span:contains("gold")').length, "should contain newly added tag 'gold'"); // save the record (should do the write RPC with the correct commands) @@ -4059,7 +4059,7 @@ QUnit.module('relational_fields', { }); QUnit.test('fieldmany2many tags in editable list', function (assert) { - assert.expect(5); + assert.expect(4); this.data.partner.records[0].timmy = [12]; @@ -4073,13 +4073,13 @@ QUnit.module('relational_fields', { '</tree>', }); - assert.strictEqual(list.$('.o_data_row:first .o_form_field_many2manytags .badge').length, 1, + assert.strictEqual(list.$('.o_data_row:first .o_field_many2manytags .badge').length, 1, "m2m field should contain one tag"); // edit first row list.$('.o_data_row:first td:nth(2)').click(); - var $m2o = list.$('.o_data_row:first .o_form_field_many2manytags .o_form_field_many2one'); + var $m2o = list.$('.o_data_row:first .o_field_many2manytags .o_field_many2one'); assert.strictEqual($m2o.length, 1, "a many2one widget should have been instantiated"); // add a tag @@ -4087,15 +4087,13 @@ QUnit.module('relational_fields', { $input.click(); $input.autocomplete('widget').find('li:first()').click(); // adds a tag - assert.strictEqual(list.$('.o_data_row:first .o_form_field_many2manytags .badge').length, 2, + assert.strictEqual(list.$('.o_data_row:first .o_field_many2manytags .badge').length, 2, "m2m field should contain 2 tags"); - assert.ok(list.$('.o_data_row:first .o_many2many_tags_cell').hasClass('o_field_dirty'), - "edited cell should have class o_field_dirty"); // leave edition list.$('.o_data_row:nth(1) td:nth(2)').click(); - assert.strictEqual(list.$('.o_data_row:first .o_form_field_many2manytags .badge').length, 2, + assert.strictEqual(list.$('.o_data_row:first .o_field_many2manytags .badge').length, 2, "m2m field should contain 2 tags"); list.destroy(); @@ -4121,31 +4119,31 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 1, + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 1, "should contain one tag"); // update foo, which will trigger an onchange and update timmy // -> m2mtags input should not have taken the focus - form.$('.o_form_input:first').focus(); - form.$('.o_form_input:first').val('trigger onchange').trigger('input'); - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 0, + form.$('input:first').focus(); + form.$('input:first').val('trigger onchange').trigger('input'); + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 0, "should contain no tags"); - assert.strictEqual(form.$('.o_form_input:first').get(0), document.activeElement, + assert.strictEqual(form.$('input:first').get(0), document.activeElement, "foo input should have kept the focus"); // add a tag -> m2mtags input should still have the focus - form.$('.o_form_field_many2manytags input').click(); // opens the dropdown - form.$('.o_form_field_many2manytags input').autocomplete('widget').find('li:first').click(); - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 1, + form.$('.o_field_many2manytags input').click(); // opens the dropdown + form.$('.o_field_many2manytags input').autocomplete('widget').find('li:first').click(); + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 1, "should contain a tag"); - assert.strictEqual(form.$('.o_form_field_many2manytags input').get(0), document.activeElement, + assert.strictEqual(form.$('.o_field_many2manytags input').get(0), document.activeElement, "m2m tags input should have kept the focus"); // remove a tag -> m2mtags input should still have the focus - form.$('.o_form_field_many2manytags .o_delete').click(); - assert.strictEqual(form.$('.o_form_field_many2manytags > span').length, 0, + form.$('.o_field_many2manytags .o_delete').click(); + assert.strictEqual(form.$('.o_field_many2manytags > span').length, 0, "should contain no tags"); - assert.strictEqual(form.$('.o_form_field_many2manytags input').get(0), document.activeElement, + assert.strictEqual(form.$('.o_field_many2manytags input').get(0), document.activeElement, "m2m tags input should have kept the focus"); form.destroy(); @@ -4166,11 +4164,11 @@ QUnit.module('relational_fields', { }); assert.ok(form.$('div.o_radio_item').length, "should have rendered outer div"); - assert.strictEqual(form.$('input.o_form_radio').length, 2, "should have 2 possible choices"); + assert.strictEqual(form.$('input.o_radio_input').length, 2, "should have 2 possible choices"); assert.ok(form.$('label.o_form_label:contains(xphone)').length, "one of them should be xphone"); assert.strictEqual(form.$('input:checked').length, 0, "none of the input should be checked"); - form.$("input.o_form_radio:first").click(); + form.$("input.o_radio_input:first").click(); assert.strictEqual(form.$('input:checked').length, 1, "one of the input should be checked"); @@ -4201,11 +4199,11 @@ QUnit.module('relational_fields', { }); form.$("input[type='checkbox']").click(); - assert.strictEqual(form.$('input.o_form_radio[data-value="37"]:checked').length, 1, "one of the input should be checked"); - assert.strictEqual(form.$('input.o_form_radio[data-value="black"]:checked').length, 1, "the other of the input should be checked"); + assert.strictEqual(form.$('input.o_radio_input[data-value="37"]:checked').length, 1, "one of the input should be checked"); + assert.strictEqual(form.$('input.o_radio_input[data-value="black"]:checked').length, 1, "the other of the input should be checked"); form.$("input[type='checkbox']").click(); - assert.strictEqual(form.$('input.o_form_radio[data-value="41"]:checked').length, 1, "the other of the input should be checked"); - assert.strictEqual(form.$('input.o_form_radio[data-value="red"]:checked').length, 1, "one of the input should be checked"); + assert.strictEqual(form.$('input.o_radio_input[data-value="41"]:checked').length, 1, "the other of the input should be checked"); + assert.strictEqual(form.$('input.o_radio_input[data-value="red"]:checked').length, 1, "one of the input should be checked"); form.destroy(); }); @@ -4225,11 +4223,11 @@ QUnit.module('relational_fields', { assert.ok(form.$('div.o_radio_item').length, "should have rendered outer div"); - assert.strictEqual(form.$('input.o_form_radio').length, 2, "should have 2 possible choices"); + assert.strictEqual(form.$('input.o_radio_input').length, 2, "should have 2 possible choices"); assert.ok(form.$('label.o_form_label:contains(Red)').length, "one of them should be Red"); // click on 2nd option - form.$("input.o_form_radio").eq(1).click(); + form.$("input.o_radio_input").eq(1).click(); form.$buttons.find('.o_form_button_save').click(); @@ -4254,24 +4252,24 @@ QUnit.module('relational_fields', { res_id: 1, }); - assert.strictEqual(form.$('div.o_form_field div.o_checkbox').length, 2, + assert.strictEqual(form.$('div.o_field_widget div.o_checkbox').length, 2, "should have fetched and displayed the 2 values of the many2many"); - assert.ok(form.$('div.o_form_field div.o_checkbox input').eq(0).prop('checked'), + assert.ok(form.$('div.o_field_widget div.o_checkbox input').eq(0).prop('checked'), "first checkbox should be checked"); - assert.notOk(form.$('div.o_form_field div.o_checkbox input').eq(1).prop('checked'), + assert.notOk(form.$('div.o_field_widget div.o_checkbox input').eq(1).prop('checked'), "second checkbox should not be checked"); - assert.ok(form.$('div.o_form_field div.o_checkbox input').prop('disabled'), + assert.ok(form.$('div.o_field_widget div.o_checkbox input').prop('disabled'), "the checkboxes should be disabled"); form.$buttons.find('.o_form_button_edit').click(); - assert.notOk(form.$('div.o_form_field div.o_checkbox input').prop('disabled'), + assert.notOk(form.$('div.o_field_widget div.o_checkbox input').prop('disabled'), "the checkboxes should not be disabled"); // add a m2m value - form.$('div.o_form_field div.o_checkbox input').eq(1).click(); + form.$('div.o_field_widget div.o_checkbox input').eq(1).click(); form.$buttons.find('.o_form_button_save').click(); assert.deepEqual(this.data.partner.records[0].timmy, [12, 14], "should have added the second element to the many2many"); @@ -4280,13 +4278,13 @@ QUnit.module('relational_fields', { // remove a m2m value form.$buttons.find('.o_form_button_edit').click(); - form.$('div.o_form_field div.o_checkbox input').eq(0).click(); + form.$('div.o_field_widget div.o_checkbox input').eq(0).click(); form.$buttons.find('.o_form_button_save').click(); assert.deepEqual(this.data.partner.records[0].timmy, [14], "should have removed the first element to the many2many"); - assert.notOk(form.$('div.o_form_field div.o_checkbox input').eq(0).prop('checked'), + assert.notOk(form.$('div.o_field_widget div.o_checkbox input').eq(0).prop('checked'), "first checkbox should be checked"); - assert.ok(form.$('div.o_form_field div.o_checkbox input').eq(1).prop('checked'), + assert.ok(form.$('div.o_field_widget div.o_checkbox input').eq(1).prop('checked'), "second checkbox should not be checked"); form.destroy(); @@ -4334,29 +4332,29 @@ QUnit.module('relational_fields', { }, }); - assert.strictEqual(form.$('div.o_form_field.oe_fileupload').length, 1, + assert.strictEqual(form.$('div.o_field_widget.oe_fileupload').length, 1, "there should be the attachment widget"); - assert.strictEqual(form.$('div.o_form_field.oe_fileupload .oe_attachments').children().length, 1, + assert.strictEqual(form.$('div.o_field_widget.oe_fileupload .oe_attachments').children().length, 1, "there should be no attachment"); - assert.strictEqual(form.$('div.o_form_field.oe_fileupload .o_attach').length, 0, + assert.strictEqual(form.$('div.o_field_widget.oe_fileupload .o_attach').length, 0, "there should not be an Add button (readonly)"); - assert.strictEqual(form.$('div.o_form_field.oe_fileupload .oe_attachment .oe_delete').length, 0, + assert.strictEqual(form.$('div.o_field_widget.oe_fileupload .oe_attachment .oe_delete').length, 0, "there should not be a Delete button (readonly)"); // to edit mode form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('div.o_form_field.oe_fileupload .o_attach').length, 1, + assert.strictEqual(form.$('div.o_field_widget.oe_fileupload .o_attach').length, 1, "there should be an Add button"); - assert.strictEqual(form.$('div.o_form_field.oe_fileupload .o_attach').text().trim(), "Pictures", + assert.strictEqual(form.$('div.o_field_widget.oe_fileupload .o_attach').text().trim(), "Pictures", "the button should be correctly named"); - assert.strictEqual(form.$('div.o_form_field.oe_fileupload .o_hidden_input_file form').length, 1, + assert.strictEqual(form.$('div.o_field_widget.oe_fileupload .o_hidden_input_file form').length, 1, "there should be a hidden form to upload attachments"); // TODO: add an attachment // no idea how to test this // delete the attachment - form.$('div.o_form_field.oe_fileupload .oe_attachment .oe_delete').click(); + form.$('div.o_field_widget.oe_fileupload .oe_attachment .oe_delete').click(); assert.verifySteps([ @@ -4366,7 +4364,7 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('div.o_form_field.oe_fileupload .oe_attachments').children().length, 0, + assert.strictEqual(form.$('div.o_field_widget.oe_fileupload .oe_attachments').children().length, 0, "there should be no attachment"); form.destroy(); diff --git a/addons/web/static/tests/views/calendar_tests.js b/addons/web/static/tests/views/calendar_tests.js index 59a27607678..482f3910550 100644 --- a/addons/web/static/tests/views/calendar_tests.js +++ b/addons/web/static/tests/views/calendar_tests.js @@ -198,15 +198,15 @@ QUnit.module('Views', { var $attendeesFilter = $sidebar.find('.o_calendar_filter:has(h3:contains(attendees))'); assert.ok($attendeesFilter.length, "should display 'attendees' filter"); assert.strictEqual($attendeesFilter.find('.o_calendar_filter_item').length, 3, "should display 3 filter items for 'attendees' who use write_model (2 saved + Everything)"); - assert.ok($attendeesFilter.find('.o_form_field_many2one').length, "should display one2many search bar for 'attendees' filter"); + assert.ok($attendeesFilter.find('.o_field_many2one').length, "should display one2many search bar for 'attendees' filter"); // test search bar in filter - $sidebar.find('input.o_form_input').trigger('click'); + $sidebar.find('input[type="text"]').trigger('click'); assert.strictEqual($('ul.ui-autocomplete li:not(.o_m2o_dropdown_option)').length, 2, "should display 2 choices in one2many autocomplete"); // TODO: remove :not(.o_m2o_dropdown_option) because can't have "create & edit" choice $('ul.ui-autocomplete li:first').trigger('click'); assert.strictEqual($sidebar.find('.o_calendar_filter:has(h3:contains(attendees)) .o_calendar_filter_item').length, 4, "should display 4 filter items for 'attendees'"); - $sidebar.find('input.o_form_input').trigger('click'); + $sidebar.find('input[type="text"]').trigger('click'); assert.strictEqual($('ul.ui-autocomplete li:not(.o_m2o_dropdown_option)').text(), "partner 4", "should display the last choice in one2many autocomplete"); // TODO: remove :not(.o_m2o_dropdown_option) because can't have "create & edit" choice $sidebar.find('.o_calendar_filter_item[data-id="1"] .o_remove').trigger('click'); assert.ok($('.modal button.btn:contains(Ok)').length, "should display the confirm message"); @@ -503,28 +503,28 @@ QUnit.module('Views', { $('.modal input:first').val('new event').trigger('input'); $('.modal button.btn:contains(Edit)').trigger('click'); - assert.strictEqual($('.o_form_field[name="start"] input').val(), "12/13/2016 08:00:00", + assert.strictEqual($('.o_field_widget[name="start"] input').val(), "12/13/2016 08:00:00", "should display the datetime"); $('.modal-lg .o_field_boolean[name="allday"] input').trigger('click'); - assert.strictEqual($('.o_form_field[name="start_date"] input').val(), "12/13/2016", + assert.strictEqual($('.o_field_widget[name="start_date"] input').val(), "12/13/2016", "should display the date"); $('.modal-lg .o_field_boolean[name="allday"] input').trigger('click'); - assert.strictEqual($('.o_form_field[name="start"] input').val(), "12/13/2016 02:00:00", + assert.strictEqual($('.o_field_widget[name="start"] input').val(), "12/13/2016 02:00:00", "should display the datetime from the date with the timezone"); // use datepicker to enter a date: 12/13/2016 08:00:00 - $('.o_form_field[name="start"] input').trigger('click'); + $('.o_field_widget[name="start"] input').trigger('click'); $('.bootstrap-datetimepicker-widget .picker-switch a[data-action="togglePicker"]').trigger('click'); $('.bootstrap-datetimepicker-widget .timepicker .timepicker-hour').trigger('click'); $('.bootstrap-datetimepicker-widget .timepicker-hours td.hour:contains(08)').trigger('click'); $('.bootstrap-datetimepicker-widget .picker-switch a[data-action="close"]').trigger('click'); // use datepicker to enter a date: 12/13/2016 10:00:00 - $('.o_form_field[name="stop"] input').trigger('click'); + $('.o_field_widget[name="stop"] input').trigger('click'); $('.bootstrap-datetimepicker-widget .picker-switch a[data-action="togglePicker"]').trigger('click'); $('.bootstrap-datetimepicker-widget .timepicker .timepicker-hour').trigger('click'); $('.bootstrap-datetimepicker-widget .timepicker-hours td.hour:contains(10)').trigger('click'); diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js index f09d98d641e..5e22dad990c 100644 --- a/addons/web/static/tests/views/form_tests.js +++ b/addons/web/static/tests/views/form_tests.js @@ -141,7 +141,7 @@ QUnit.module('Views', { assert.strictEqual(form.$('.o_group .o_group:first').attr('style'), 'background-color: red', "should apply style attribute on groups"); - assert.strictEqual(form.$('.o_form_field[name=foo]').attr('style'), 'color: blue', + assert.strictEqual(form.$('.o_field_widget[name=foo]').attr('style'), 'color: blue', "should apply style attribute on fields"); assert.strictEqual(form.$('label:contains(something_id)').length, 0, @@ -226,11 +226,11 @@ QUnit.module('Views', { res_id: 1, }); - assert.strictEqual(form.$('label.o_form_invisible:contains(Foo)').length, 1, + assert.strictEqual(form.$('label.o_invisible_modifier:contains(Foo)').length, 1, "should not contain label Foo"); - assert.strictEqual(form.$('span.o_form_invisible:contains(yop)').length, 1, + assert.strictEqual(form.$('span.o_invisible_modifier:contains(yop)').length, 1, "should not contain span with field value"); - assert.strictEqual(form.$('.o_form_field.o_form_invisible:contains(0.4)').length, 1, + assert.strictEqual(form.$('.o_field_widget.o_invisible_modifier:contains(0.4)').length, 1, "field qux should be invisible"); form.destroy(); }); @@ -257,9 +257,9 @@ QUnit.module('Views', { '</form>', res_id: 1, }); - assert.strictEqual(form.$('.o_notebook li.o_form_invisible a:contains(invisible)').length, 1, + assert.strictEqual(form.$('.o_notebook li.o_invisible_modifier a:contains(invisible)').length, 1, "should not display tab invisible"); - assert.strictEqual(form.$('table.o_inner_group.o_form_invisible td:contains(invgroup)').length, 1, + assert.strictEqual(form.$('table.o_inner_group.o_invisible_modifier td:contains(invgroup)').length, 1, "should not display invisible groups"); form.destroy(); }); @@ -287,14 +287,14 @@ QUnit.module('Views', { form.$buttons.find('.o_form_button_edit').click(); - assert.ok(form.$('.foo_field').hasClass('o_form_invisible'), 'should not display foo field'); - assert.ok(form.$('.bar_field').hasClass('o_form_invisible'), 'should not display bar field'); + assert.ok(form.$('.foo_field').hasClass('o_invisible_modifier'), 'should not display foo field'); + assert.ok(form.$('.bar_field').hasClass('o_invisible_modifier'), 'should not display bar field'); // set a value on the m2o - var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget'); - form.$('.o_form_field_many2one input').click(); + var $dropdown = form.$('.o_field_many2one input').autocomplete('widget'); + form.$('.o_field_many2one input').click(); $dropdown.find('li:first()').click(); - assert.ok(!form.$('.foo_field').hasClass('o_form_invisible'), 'should display foo field'); + assert.ok(!form.$('.foo_field').hasClass('o_invisible_modifier'), 'should display foo field'); form.destroy(); }); @@ -324,16 +324,16 @@ QUnit.module('Views', { form.$buttons.find('.o_form_button_edit').click(); assert.ok(form.$('.o_notebook .nav li:first()').hasClass('active'), 'first tab should be active'); - assert.ok(!form.$('.o_notebook .nav li:first()').hasClass('o_form_invisible'), + assert.ok(!form.$('.o_notebook .nav li:first()').hasClass('o_invisible_modifier'), 'first tab should be visible'); // set a value on the m2o - var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget'); - form.$('.o_form_field_many2one input').click(); + var $dropdown = form.$('.o_field_many2one input').autocomplete('widget'); + form.$('.o_field_many2one input').click(); $dropdown.find('li:first()').click(); assert.ok(!form.$('.o_notebook .nav li:first()').hasClass('active'), 'first tab should not be active'); - assert.ok(form.$('.o_notebook .nav li:first()').hasClass('o_form_invisible'), + assert.ok(form.$('.o_notebook .nav li:first()').hasClass('o_invisible_modifier'), 'first tab should be invisible'); assert.ok(form.$('.o_notebook .nav li:nth(1)').hasClass('active'), 'second tab should be active'); @@ -365,7 +365,7 @@ QUnit.module('Views', { res_id: 1, }); - assert.ok(form.$('.o_notebook .nav li:first()').hasClass('o_form_invisible'), + assert.notOk(form.$('.o_notebook .nav li:first()').is(':visible'), 'first tab should be invisible'); assert.ok(form.$('.o_notebook .nav li:nth(1)').hasClass('active'), 'second tab should be active'); @@ -452,7 +452,7 @@ QUnit.module('Views', { assert.strictEqual(form.$('button.oe_stat_button').length, 2, "should have 2 stat buttons"); - assert.strictEqual(form.$('button.oe_stat_button.o_form_invisible').length, 1, + assert.strictEqual(form.$('button.oe_stat_button.o_invisible_modifier').length, 1, "should have 1 invisible stat buttons"); var count = 0; @@ -547,29 +547,29 @@ QUnit.module('Views', { res_id: 2, }); - assert.strictEqual(form.$('.o_form_field.o_form_field_empty').length, 2, + assert.strictEqual(form.$('.o_field_widget.o_field_empty').length, 2, "should have 2 empty fields with correct class"); assert.strictEqual(form.$('.o_form_label_empty').length, 2, "should have 2 muted labels (for the empty fieds) in readonly"); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field_empty').length, 1, - "in edit mode, only empty readonly fields should have the o_form_field_empty class"); + assert.strictEqual(form.$('.o_field_empty').length, 1, + "in edit mode, only empty readonly fields should have the o_field_empty class"); assert.strictEqual(form.$('.o_form_label_empty').length, 1, "in edit mode, only labels associated to empty readonly fields should have the o_form_label_empty class"); form.$('input[name="foo"]').val("test").trigger("input"); - assert.strictEqual(form.$('.o_form_field_empty').length, 0, - "after readonly modifier change, the o_form_field_empty class should have been removed"); + assert.strictEqual(form.$('.o_field_empty').length, 0, + "after readonly modifier change, the o_field_empty class should have been removed"); assert.strictEqual(form.$('.o_form_label_empty').length, 0, "after readonly modifier change, the o_form_label_empty class should have been removed"); form.$('input[name="foo"]').val("hello").trigger("input"); - assert.strictEqual(form.$('.o_form_field_empty').length, 1, - "after value changed to false for a readonly field, the o_form_field_empty class should have been added"); + assert.strictEqual(form.$('.o_field_empty').length, 1, + "after value changed to false for a readonly field, the o_field_empty class should have been added"); assert.strictEqual(form.$('.o_form_label_empty').length, 1, "after value changed to false for a readonly field, the o_form_label_empty class should have been added"); @@ -596,7 +596,7 @@ QUnit.module('Views', { }); assert.strictEqual(form.$('.o_form_label_empty').length, 0, "no empty class on label"); - assert.strictEqual(form.$('.o_form_field_empty').length, 0, + assert.strictEqual(form.$('.o_field_empty').length, 0, "no empty class on field"); form.destroy(); }); @@ -657,19 +657,19 @@ QUnit.module('Views', { }); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input[name="foo"].o_form_required').length, 1, + assert.strictEqual(form.$('input[name="foo"].o_required_modifier').length, 1, "the foo field widget should be required"); form.$('.o_field_boolean input').click(); - assert.strictEqual(form.$('input[name="foo"]:not(.o_form_required)').length, 1, + assert.strictEqual(form.$('input[name="foo"]:not(.o_required_modifier)').length, 1, "the foo field widget should now have been marked as non-required"); form.$('.o_field_boolean input').click(); - assert.strictEqual(form.$('input[name="foo"].o_form_required').length, 1, + assert.strictEqual(form.$('input[name="foo"].o_required_modifier').length, 1, "the foo field widget should now have been marked as required again"); form.destroy(); }); - QUnit.test('required fields should have o_form_required in readonly mode', function (assert) { + QUnit.test('required fields should have o_required_modifier in readonly mode', function (assert) { assert.expect(2); this.data.partner.fields.foo.required = true; @@ -687,12 +687,12 @@ QUnit.module('Views', { res_id: 1, }); - assert.strictEqual(form.$('span.o_form_required').length, 1, - "should have 1 span with o_form_required class"); + assert.strictEqual(form.$('span.o_required_modifier').length, 1, + "should have 1 span with o_required_modifier class"); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('input.o_form_required').length, 1, - "in edit mode, should have 1 input with o_form_required"); + assert.strictEqual(form.$('input.o_required_modifier').length, 1, + "in edit mode, should have 1 input with o_required_modifier"); form.destroy(); }); @@ -1186,7 +1186,7 @@ QUnit.module('Views', { return this._super.apply(this, arguments); }, }).then(function (form) { - assert.ok(form.$('.o_form_input').val(), 'aaa', + assert.ok(form.$('input').val(), 'aaa', 'default value should be correctly displayed'); assert.strictEqual(nameGetCount, 1, 'should have done one name_get'); form.destroy(); @@ -1464,12 +1464,12 @@ QUnit.module('Views', { // switch to edit mode form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input').val(), 'yop', 'input should contain yop'); + assert.strictEqual(form.$('input').val(), 'yop', 'input should contain yop'); // click on discard form.$buttons.find('.o_form_button_cancel').click(); assert.ok(!$('.modal:visible').length, 'no confirm modal should be displayed'); - assert.strictEqual(form.$('.o_form_field').text(), 'yop', 'field in readonly should display yop'); + assert.strictEqual(form.$('.o_field_widget').text(), 'yop', 'field in readonly should display yop'); assert.strictEqual(nbWrite, 0, 'no write RPC should have been done'); form.destroy(); @@ -1495,21 +1495,21 @@ QUnit.module('Views', { // switch to edit mode and edit the foo field form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input').val(), 'yop', 'input should contain yop'); - form.$('.o_form_input').val('new value').trigger('input'); - assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should contain new value'); + assert.strictEqual(form.$('input').val(), 'yop', 'input should contain yop'); + form.$('input').val('new value').trigger('input'); + assert.strictEqual(form.$('input').val(), 'new value', 'input should contain new value'); // click on discard and cancel the confirm request form.$buttons.find('.o_form_button_cancel').click(); assert.ok($('.modal').length, 'a confirm modal should be displayed'); $('.modal .modal-footer .btn-default').click(); // click on cancel - assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should still contain new value'); + assert.strictEqual(form.$('input').val(), 'new value', 'input should still contain new value'); // click on discard and confirm form.$buttons.find('.o_form_button_cancel').click(); assert.ok($('.modal').length, 'a confirm modal should be displayed'); $('.modal .modal-footer .btn-primary').click(); // click on confirm - assert.strictEqual(form.$('.o_form_field').text(), 'yop', 'field in readonly should display yop'); + assert.strictEqual(form.$('.o_field_widget').text(), 'yop', 'field in readonly should display yop'); assert.strictEqual(nbWrite, 0, 'no write RPC should have been done'); form.destroy(); @@ -1524,7 +1524,6 @@ QUnit.module('Views', { // then parsed into string, which is wrong. this.data.partner.fields.date.default = "2017-01-25"; - var nbWrite = 0; var form = createView({ View: FormView, model: 'partner', @@ -1580,12 +1579,12 @@ QUnit.module('Views', { // switch to edit mode and edit the p field form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); - form.$('.o_form_field_many2one input').click(); - var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget'); + form.$('.o_field_x2many_list_row_add a').click(); + form.$('.o_field_many2one input').click(); + var $dropdown = form.$('.o_field_many2one input').autocomplete('widget'); $dropdown.find('li:first()').click(); - assert.strictEqual(form.$('.o_form_input').val(), 'xphone', 'input should contain xphone'); + assert.strictEqual(form.$('input').val(), 'xphone', 'input should contain xphone'); // click on discard and confirm form.$buttons.find('.o_form_button_cancel').click(); @@ -1615,7 +1614,7 @@ QUnit.module('Views', { // switch to edit mode and edit the foo field form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input').val(), 'ABC', 'input should contain ABC'); + assert.strictEqual(form.$('input').val(), 'ABC', 'input should contain ABC'); form.$buttons.find('.o_form_button_cancel').click(); @@ -1647,25 +1646,24 @@ QUnit.module('Views', { }, }); - // switch to edit mode and edit the foo field - form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input').val(), 'ABC', 'input should contain ABC'); - form.$('.o_form_input').val('DEF').trigger('input'); + // edit the foo field + assert.strictEqual(form.$('input').val(), 'ABC', 'input should contain ABC'); + form.$('input').val('DEF').trigger('input'); // discard the changes and check it has properly been discarded form.$buttons.find('.o_form_button_cancel').click(); assert.strictEqual($('.modal').length, 1, 'there should be a confirm modal'); - assert.strictEqual(form.$('.o_form_input').val(), 'DEF', 'input should be DEF'); + assert.strictEqual(form.$('input').val(), 'DEF', 'input should be DEF'); $('.modal .modal-footer .btn-primary').click(); // click on confirm - assert.strictEqual(form.$('.o_form_input').val(), 'ABC', 'input should now be ABC'); + assert.strictEqual(form.$('input').val(), 'ABC', 'input should now be ABC'); // redirty and discard the field foo (to make sure initial changes haven't been lost) - form.$('.o_form_input').val('GHI').trigger('input'); + form.$('input').val('GHI').trigger('input'); form.$buttons.find('.o_form_button_cancel').click(); - assert.strictEqual(form.$('.o_form_input').val(), 'GHI', 'input should be GHI'); + assert.strictEqual(form.$('input').val(), 'GHI', 'input should be GHI'); $('.modal .modal-footer .btn-primary').click(); // click on confirm - assert.strictEqual(form.$('.o_form_input').val(), 'ABC', 'input should now be ABC'); + assert.strictEqual(form.$('input').val(), 'ABC', 'input should now be ABC'); form.destroy(); }); @@ -1694,7 +1692,7 @@ QUnit.module('Views', { form.sidebar.$('a:contains(Duplicate)').click(); - assert.strictEqual(form.$('.o_form_input').val(), 'tralala', 'input should contain ABC'); + assert.strictEqual(form.$('input').val(), 'tralala', 'input should contain ABC'); form.$buttons.find('.o_form_button_cancel').click(); @@ -1731,24 +1729,24 @@ QUnit.module('Views', { // switch to edit mode form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input').val(), 'yop', 'input should contain yop'); + assert.strictEqual(form.$('input').val(), 'yop', 'input should contain yop'); // edit the foo field - form.$('.o_form_input').val('new value').trigger('input'); - assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should contain new value'); + form.$('input').val('new value').trigger('input'); + assert.strictEqual(form.$('input').val(), 'new value', 'input should contain new value'); // click on the pager to switch to the next record and cancel the confirm request form.pager.$('.o_pager_next').click(); // click on next assert.ok($('.modal').length, 'a confirm modal should be displayed'); $('.modal .modal-footer .btn-default').click(); // click on cancel - assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should still contain new value'); + assert.strictEqual(form.$('input').val(), 'new value', 'input should still contain new value'); assert.strictEqual(form.pager.$('.o_pager_value').text(), "1", 'pager value should still be 1'); // click on the pager to switch to the next record and confirm form.pager.$('.o_pager_next').click(); // click on next assert.ok($('.modal').length, 'a confirm modal should be displayed'); $('.modal .modal-footer .btn-primary').click(); // click on confirm - assert.strictEqual(form.$('.o_form_input').val(), 'blip', 'input should contain blip'); + assert.strictEqual(form.$('input').val(), 'blip', 'input should contain blip'); assert.strictEqual(form.pager.$('.o_pager_value').text(), "2", 'pager value should be 2'); assert.strictEqual(nbWrite, 0, 'no write RPC should have been done'); @@ -1776,11 +1774,11 @@ QUnit.module('Views', { // switch to edit mode form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input').val(), 'yop', 'input should contain yop'); + assert.strictEqual(form.$('input').val(), 'yop', 'input should contain yop'); // edit the foo field - form.$('.o_form_input').val('new value').trigger('input'); - assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should contain new value'); + form.$('input').val('new value').trigger('input'); + assert.strictEqual(form.$('input').val(), 'new value', 'input should contain new value'); form.$buttons.find('.o_form_button_save').click(); @@ -1803,10 +1801,10 @@ QUnit.module('Views', { // switch to edit mode form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input').val(), 'new value', 'input should contain yop'); + assert.strictEqual(form.$('input').val(), 'new value', 'input should contain yop'); // edit the foo field - form.$('.o_form_input').val('wrong value').trigger('input'); + form.$('input').val('wrong value').trigger('input'); form.$buttons.find('.o_form_button_cancel').click(); assert.strictEqual($('.modal').length, 1, 'a confirm modal should be displayed'); @@ -1976,12 +1974,12 @@ QUnit.module('Views', { res_id: 1, }); - assert.strictEqual(form.$('.o_form_field_empty').length, 1, + assert.strictEqual(form.$('.o_field_empty').length, 1, 'readonly field should be invisible on an existing record'); form.$buttons.find('.o_form_button_create').click(); - assert.strictEqual(form.$('.o_form_field_empty').length, 0, + assert.strictEqual(form.$('.o_field_empty').length, 0, 'readonly field should be visible on a new record'); form.destroy(); }); @@ -2119,15 +2117,15 @@ QUnit.module('Views', { }); form.$buttons.find('.o_form_button_save').click(); - assert.ok(form.$('label').hasClass('o_form_invalid'), + assert.ok(form.$('label').hasClass('o_field_invalid'), "label should be tagged as invalid"); - assert.ok(form.$('input').hasClass('o_form_invalid'), + assert.ok(form.$('input').hasClass('o_field_invalid'), "input should be tagged as invalid"); form.$('input').val("tralala").trigger('input'); form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_invalid').length, 0, + assert.strictEqual(form.$('.o_field_invalid').length, 0, "nothing should be marked as invalid"); form.destroy(); }); @@ -2224,12 +2222,12 @@ QUnit.module('Views', { form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input[name=int_field]').val(), '9', + assert.strictEqual(form.$('input[name=int_field]').val(), '9', "'int_field' value should be 9 before the change"); form.$('input').first().val("tralala").trigger('input'); - assert.strictEqual(form.$('.o_form_input[name=int_field]').val(), '10', + assert.strictEqual(form.$('input[name=int_field]').val(), '10', "the onchange should have been correctly applied"); form.destroy(); @@ -2273,7 +2271,7 @@ QUnit.module('Views', { // go to edit mode, click to add a record in the o2m form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); assert.strictEqual(form.$('tr.o_data_row').length, 0, "should not have added a line"); form.destroy(); @@ -2379,15 +2377,15 @@ QUnit.module('Views', { res_id: 1, }); - assert.strictEqual(form.$('.o_form_field_one2many .o_data_row').length, 1, + assert.strictEqual(form.$('.o_field_one2many .o_data_row').length, 1, "there should be one one2many record linked at first"); - assert.strictEqual(form.$('.o_form_field_one2many .o_data_row td:first').text(), 'aaa', + assert.strictEqual(form.$('.o_field_one2many .o_data_row td:first').text(), 'aaa', "the 'display_name' of the one2many record should be correct"); // switch to edit mode form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_input').val('let us trigger an onchange').trigger('input'); - var $o2m = form.$('.o_form_field_one2many'); + form.$('input').val('let us trigger an onchange').trigger('input'); + var $o2m = form.$('.o_field_one2many'); assert.strictEqual($o2m.find('.o_data_row').length, 2, "there should be two linked record"); assert.strictEqual($o2m.find('.o_data_row:first td:first').text(), 'updated record', @@ -2479,13 +2477,13 @@ QUnit.module('Views', { res_id: 2, }); - assert.strictEqual(form.$('.o_form_field_many2many .o_data_row').length, 0, + assert.strictEqual(form.$('.o_field_many2many .o_data_row').length, 0, "there should be no many2many record linked at first"); // switch to edit mode form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_input').val('let us trigger an onchange').trigger('input'); - var $m2m = form.$('.o_form_field_many2many'); + form.$('input').val('let us trigger an onchange').trigger('input'); + var $m2m = form.$('.o_field_many2many'); assert.strictEqual($m2m.find('.o_data_row').length, 2, "there should be two linked records"); assert.strictEqual($m2m.find('.o_data_row:first td:first').text(), 'gold', @@ -2526,24 +2524,24 @@ QUnit.module('Views', { }, }); - assert.strictEqual(form.$('.o_form_field[name=date]').text(), + assert.strictEqual(form.$('.o_field_widget[name=date]').text(), '01/25/2017', "the initial date should be correct"); - assert.strictEqual(form.$('.o_form_field[name=datetime]').text(), + assert.strictEqual(form.$('.o_field_widget[name=datetime]').text(), '12/12/2016 12:55:05', "the initial datetime should be correct"); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_field[name=date] input').val(), + assert.strictEqual(form.$('.o_field_widget[name=date] input').val(), '01/25/2017', "the initial date should be correct in edit"); - assert.strictEqual(form.$('.o_form_field[name=datetime] input').val(), + assert.strictEqual(form.$('.o_field_widget[name=datetime] input').val(), '12/12/2016 12:55:05', "the initial datetime should be correct in edit"); // trigger the onchange - form.$('.o_form_field[name="foo"]').val("coucou").trigger('input'); + form.$('.o_field_widget[name="foo"]').val("coucou").trigger('input'); - assert.strictEqual(form.$('.o_form_field[name=date] input').val(), + assert.strictEqual(form.$('.o_field_widget[name=date] input').val(), '12/12/2021', "the initial date should be correct in edit"); - assert.strictEqual(form.$('.o_form_field[name=datetime] input').val(), + assert.strictEqual(form.$('.o_field_widget[name=datetime] input').val(), '12/12/2021 12:55:05', "the initial datetime should be correct in edit"); form.destroy(); @@ -2653,7 +2651,7 @@ QUnit.module('Views', { // save, and check that the int_field input is marked as invalid form.$buttons.find('.o_form_button_save').click(); - assert.ok(form.$('input[name="int_field"]').hasClass('o_form_invalid'), + assert.ok(form.$('input[name="int_field"]').hasClass('o_field_invalid'), "input int_field is marked as invalid"); assert.verifySteps(['read', 'onchange']); @@ -2769,7 +2767,7 @@ QUnit.module('Views', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_input:first').val('trigger an onchange').trigger('input'); + form.$('input:first').val('trigger an onchange').trigger('input'); form.destroy(); }); @@ -2830,7 +2828,7 @@ QUnit.module('Views', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_input:first').val('trigger an onchange').trigger('input'); + form.$('input:first').val('trigger an onchange').trigger('input'); assert.strictEqual(form.$('.o_data_row td:first').text(), 'foo changed', "onchange should have been correctly applied on field in o2m list"); @@ -2890,13 +2888,13 @@ QUnit.module('Views', { assert.strictEqual(form.$('.o_data_row td:first').text(), 'My little Foo Value', "the initial value should be the default one"); - form.$('.o_form_input:first').val('trigger an onchange').trigger('input'); + form.$('input:first').val('trigger an onchange').trigger('input'); assert.strictEqual(form.$('.o_data_row td:first').text(), 'foo changed', "onchange should have been correctly applied on field in o2m list"); form.$('.o_data_row').click(); // edit the o2m in the dialog - assert.strictEqual($('.modal .o_form_field').val(), 'foo changed', + assert.strictEqual($('.modal .o_field_widget').val(), 'foo changed', "the onchange value hasn't been discarded when opening the o2m"); form.destroy(); @@ -2943,7 +2941,7 @@ QUnit.module('Views', { "onchange should have been correctly applied"); // create a new o2m record - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); assert.strictEqual(form.$('.o_data_row input:first').val(), '[blip] 14', "onchange should have been correctly applied after default get"); @@ -2988,16 +2986,16 @@ QUnit.module('Views', { "the initial value should be the default one"); form.$('.o_data_row td:first').click(); // edit the o2m in a dialog - $('.modal .o_form_input:nth(1)').val(77).trigger('input'); - assert.strictEqual($('.modal .o_form_input:first').val(), '[blip] 77', + $('.modal input:nth(1)').val(77).trigger('input'); + assert.strictEqual($('.modal input:first').val(), '[blip] 77', "onchange should have been correctly applied"); $('.modal .modal-footer .btn-primary').click(); // save the dialog assert.strictEqual(form.$('.o_data_row td:first').text(), '[blip] 77', "onchange should have been correctly applied"); // create a new o2m record - form.$('.o_form_field_x2many_list_row_add a').click(); - assert.strictEqual($('.modal .o_form_input:first').val(), '[blip] 14', + form.$('.o_field_x2many_list_row_add a').click(); + assert.strictEqual($('.modal input:first').val(), '[blip] 14', "onchange should have been correctly applied after default get"); $('.modal .modal-footer .btn-primary').click(); // save the dialog assert.strictEqual(form.$('.o_data_row:nth(1) td:first').text(), '[blip] 14', @@ -3035,7 +3033,7 @@ QUnit.module('Views', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_input:first').val('coucou').trigger('input'); + form.$('input:first').val('coucou').trigger('input'); form.destroy(); }); @@ -3260,10 +3258,10 @@ QUnit.module('Views', { }); // add a o2m subrecord with a m2m tag - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); form.$('.o_many2many_tags_cell').click(); - form.$('.o_form_field_many2one input').click(); - var $dropdown = form.$('.o_form_field_many2one input').autocomplete('widget'); + form.$('.o_field_many2one input').click(); + var $dropdown = form.$('.o_field_many2one input').autocomplete('widget'); $dropdown.find('li:first()').click(); // select the first tag form.$buttons.find('.o_form_button_save').click(); @@ -3345,13 +3343,13 @@ QUnit.module('Views', { // could be saved, even if in its field description it is readonly form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input').length, 1, + assert.strictEqual(form.$('input[name="foo"]').length, 1, "foo field should be editable"); - form.$('.o_form_input').val('New foo value').trigger('input'); + form.$('input[name="foo"]').val('New foo value').trigger('input'); form.$buttons.find('.o_form_button_save').click(); - assert.strictEqual(form.$('.o_form_field[name=foo]').text(), 'New foo value', + assert.strictEqual(form.$('.o_field_widget[name=foo]').text(), 'New foo value', "new value for foo field should have been saved"); form.destroy(); @@ -3388,7 +3386,7 @@ QUnit.module('Views', { }); form.$buttons.find('.o_form_button_edit').click(); - form.$('.o_form_field_x2many_list_row_add a').click(); + form.$('.o_field_x2many_list_row_add a').click(); form.destroy(); }); @@ -3428,7 +3426,7 @@ QUnit.module('Views', { form.destroy(); function getVisibleButtonTexts() { - var $visibleButtons = form.$buttons.find('button').not('.o_form_invisible *'); + var $visibleButtons = form.$buttons.find('button:visible'); return _.map($visibleButtons, function (el) { return el.innerHTML.trim(); }); @@ -3525,11 +3523,11 @@ QUnit.module('Views', { return this._super.apply(this, arguments); }, }); - var row = form.$('.o_form_field_one2many .o_list_view .o_data_row'); + var row = form.$('.o_field_one2many .o_list_view .o_data_row'); assert.strictEqual(row.children()[1].textContent, '1 record', "the cell should contains the number of record: 1"); row.click(); - var modal_row = $('.modal-body .o_form_sheet .o_form_field_one2many .o_list_view .o_data_row'); + var modal_row = $('.modal-body .o_form_sheet .o_field_one2many .o_list_view .o_data_row'); assert.strictEqual(modal_row.children().length, 2, "the row should contains the 2 fields defined in the form view"); assert.strictEqual($(modal_row).text(), "gold2", @@ -3554,9 +3552,9 @@ QUnit.module('Views', { }); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input[name="foo"]')[0], document.activeElement, + assert.strictEqual(form.$('input[name="foo"]')[0], document.activeElement, "foo field should have focus"); - assert.strictEqual(form.$('.o_form_input[name="foo"]')[0].selectionStart, 3, + assert.strictEqual(form.$('input[name="foo"]')[0].selectionStart, 3, "cursor should be at the end"); form.destroy(); @@ -3576,7 +3574,7 @@ QUnit.module('Views', { res_id: 1, }); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_form_input[name="foo"]')[0], document.activeElement, + assert.strictEqual(form.$('input[name="foo"]')[0], document.activeElement, "foo field should have focus"); form.destroy(); @@ -3646,7 +3644,7 @@ QUnit.module('Views', { return this._super.apply(this, arguments); }, }); - var row = form.$('.o_form_field_one2many .o_list_view .o_data_row'); + var row = form.$('.o_field_one2many .o_list_view .o_data_row'); row.click(); assert.verifySteps(['read', 'read', 'read'], "there should be 3 read rpcs"); @@ -3809,16 +3807,16 @@ QUnit.module('Views', { assert.strictEqual($('.modal').length, 1, "One FormViewDialog should be opened"); var $firstModal = $('.modal'); - assert.strictEqual($firstModal.find('.o_form_input').val(), 'xphone', + assert.strictEqual($firstModal.find('input').val(), 'xphone', "display_name should be correctly displayed"); // Open second dialog - $firstModal.find('.o_form_field_x2many_list_row_add a').click(); + $firstModal.find('.o_field_x2many_list_row_add a').click(); assert.strictEqual($('.modal').length, 2, "two FormViewDialogs should be opened"); var $secondModal = $('.modal:nth(1)'); // Add new value - $secondModal.find('.o_form_input').val('xtv').trigger('input'); + $secondModal.find('input').val('xtv').trigger('input'); $secondModal.find('.modal-footer button:first').click(); // Save & close assert.strictEqual($('.modal').length, 1, "last opened dialog should be closed"); @@ -3858,7 +3856,7 @@ QUnit.module('Views', { }, }); - form.$('.o_form_input:first').click(); // trigger the name_search + form.$('input:first').click(); // trigger the name_search form.destroy(); }); @@ -3889,21 +3887,21 @@ QUnit.module('Views', { res_id: 1, }); - assert.strictEqual(form.$('.o_notebook ul li:not(.o_form_invisible)').length, 2, + assert.strictEqual(form.$('.o_notebook ul li:not(.o_invisible_modifier)').length, 2, "both tabs should be visible"); assert.ok(form.$('.o_notebook ul li:first').hasClass('active'), "first tab should be active"); // click on the pager to switch to the next record form.pager.$('.o_pager_next').click(); - assert.strictEqual(form.$('.o_notebook ul li:not(.o_form_invisible)').length, 1, + assert.strictEqual(form.$('.o_notebook ul li:not(.o_invisible_modifier)').length, 1, "only the second tab should be visible"); - assert.ok(form.$('.o_notebook ul li:not(.o_form_invisible)').hasClass('active'), + assert.ok(form.$('.o_notebook ul li:not(.o_invisible_modifier)').hasClass('active'), "the visible tab should be active"); // click on the pager to switch back to the previous record form.pager.$('.o_pager_previous').click(); - assert.strictEqual(form.$('.o_notebook ul li:not(.o_form_invisible)').length, 2, + assert.strictEqual(form.$('.o_notebook ul li:not(.o_invisible_modifier)').length, 2, "both tabs should be visible again"); assert.ok(form.$('.o_notebook ul li:nth(1)').hasClass('active'), "second tab should be active"); @@ -4013,7 +4011,7 @@ QUnit.module('Views', { res_id: 1, }); - assert.ok(form.$('.o_form_field_one2many tbody tr:first td:contains(yop)').length, + assert.ok(form.$('.o_field_one2many tbody tr:first td:contains(yop)').length, "record 1 should be first"); form.destroy(); diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js index e06adb394a2..debb65b60ff 100644 --- a/addons/web/static/tests/views/kanban_tests.js +++ b/addons/web/static/tests/views/kanban_tests.js @@ -403,11 +403,11 @@ QUnit.module('Views', { assert.strictEqual($('.modal .o_form_view.o_form_editable').length, 1, "a form view dialog should have been opened (in edit)"); - assert.strictEqual($('.modal .o_form_field_many2one input').val(), 'hello', + assert.strictEqual($('.modal .o_field_many2one input').val(), 'hello', "the correct product_id should already be set"); // specify a name and save - $('.modal .o_form_input[name=foo]').val('test').trigger('input'); + $('.modal input[name=foo]').val('test').trigger('input'); $('.modal-footer .btn-primary').click(); assert.strictEqual($('.modal').length, 0, "the modal should be closed"); @@ -445,7 +445,7 @@ QUnit.module('Views', { }); var $first_record = kanban.$('.o_kanban_record:first()'); - assert.strictEqual($first_record.find('.o_form_field_many2manytags .o_tag').length, 2, + assert.strictEqual($first_record.find('.o_field_many2manytags .o_tag').length, 2, 'first record should contain 2 tags'); assert.ok($first_record.find('.o_tag:first()').hasClass('o_tag_color_2'), 'first tag should have color 2'); @@ -751,9 +751,9 @@ QUnit.module('Views', { // edit the title of column [5, 'xmo'] and close without saving kanban.$('.o_kanban_group[data-id=5] .o_column_edit').click(); // click on 'Edit' assert.ok($('.modal .o_form_editable').length, 'a form view should be open in a modal'); - assert.strictEqual($('.modal .o_form_editable .o_form_input').val(), 'xmo', + assert.strictEqual($('.modal .o_form_editable input').val(), 'xmo', 'the name should be "xmo"'); - $('.modal .o_form_editable .o_form_input').val('ged').trigger('input'); // change the value + $('.modal .o_form_editable input').val('ged').trigger('input'); // change the value nbRPCs = 0; $('.modal .modal-header .close').click(); // click on the cross to close the modal assert.ok(!$('.modal').length, 'the modal should be closed'); @@ -763,7 +763,7 @@ QUnit.module('Views', { // edit the title of column [5, 'xmo'] and discard kanban.$('.o_kanban_group[data-id=5] .o_column_edit').click(); // click on 'Edit' - $('.modal .o_form_editable .o_form_input').val('ged').trigger('input'); // change the value + $('.modal .o_form_editable input').val('ged').trigger('input'); // change the value nbRPCs = 0; $('.modal .modal-footer .btn-default').click(); // click on discard assert.ok(!$('.modal').length, 'the modal should be closed'); @@ -773,7 +773,7 @@ QUnit.module('Views', { // edit the title of column [5, 'xmo'] and save kanban.$('.o_kanban_group[data-id=5] .o_column_edit').click(); // click on 'Edit' - $('.modal .o_form_editable .o_form_input').val('ged').trigger('input'); // change the value + $('.modal .o_form_editable input').val('ged').trigger('input'); // change the value nbRPCs = 0; $('.modal .modal-footer .btn-primary').click(); // click on save assert.ok(!$('.modal').length, 'the modal should be closed'); diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index beb3b1843b1..2ec0e2ccbb4 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -302,17 +302,17 @@ QUnit.module('Views', { $td.click(); assert.ok($td.parent().hasClass('o_selected_row'), "row should be in edit mode"); - assert.ok($td.hasClass('o_readonly'), + assert.ok($td.hasClass('o_readonly_modifier'), "foo cell should be readonly in edit mode"); - assert.ok(!$second_td.hasClass('o_readonly'), + assert.ok(!$second_td.hasClass('o_readonly_modifier'), "bar cell should be editable"); - assert.ok($third_td.hasClass('o_readonly'), + assert.ok($third_td.hasClass('o_readonly_modifier'), "int_field cell should be readonly in edit mode"); list.destroy(); }); QUnit.test('basic operations for editable list renderer', function (assert) { - assert.expect(4); + assert.expect(2); var list = createView({ View: ListView, @@ -325,9 +325,6 @@ QUnit.module('Views', { assert.ok(!$td.parent().hasClass('o_selected_row'), "td should not be in edit mode"); $td.click(); assert.ok($td.parent().hasClass('o_selected_row'), "td should be in edit mode"); - assert.ok(!$td.hasClass('o_field_dirty'), "td should not be dirty"); - $td.find('input').val('abc').trigger('input'); - assert.ok($td.hasClass('o_field_dirty'), "td should be dirty"); list.destroy(); }); @@ -1085,9 +1082,9 @@ QUnit.module('Views', { // edit first row list.$('tbody tr:nth(0) td:nth(2)').click(); // click on first row to edit it - assert.strictEqual(list.$('tbody tr:nth(0) td:nth(4) input.o_form_invisible').length, 1, + assert.strictEqual(list.$('tbody tr:nth(0) td:nth(4) input.o_invisible_modifier').length, 1, "td that contains an invisible field should not be empty in edition"); - assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > button.o_form_invisible').length, 1, + assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > button.o_invisible_modifier').length, 1, "td that contains an invisible button should not be empty in edition"); list.$buttons.find('.o_list_button_discard').click(); // leave edition @@ -1161,16 +1158,16 @@ QUnit.module('Views', { arch: '<tree editable="bottom"><field name="foo"/><field name="int_field"/></tree>', }); - assert.ok(list.$('.o_data_row:first td:nth(1)').hasClass('o_readonly'), - "foo field cells should have class 'o_readonly'"); + assert.ok(list.$('.o_data_row:first td:nth(1)').hasClass('o_readonly_modifier'), + "foo field cells should have class 'o_readonly_modifier'"); // edit the first row list.$('.o_data_row:first td:nth(1)').click(); assert.ok(list.$('.o_data_row:first').hasClass('o_selected_row'), "first row should be selected"); var $cell = list.$('.o_data_row:first td:nth(1)'); - assert.ok($cell.hasClass('o_readonly') && $cell.parent().hasClass('o_selected_row'), - "foo field cells should have class 'o_readonly' and the row should be in edition"); + assert.ok($cell.hasClass('o_readonly_modifier') && $cell.parent().hasClass('o_selected_row'), + "foo field cells should have class 'o_readonly_modifier' and the row should be in edition"); assert.strictEqual(list.$('.o_data_row:first td:nth(1) span').text(), 'yop', "a widget should have been rendered for readonly fields"); assert.ok(list.$('.o_data_row:first td:nth(2)').parent().hasClass('o_selected_row'), @@ -1415,32 +1412,32 @@ QUnit.module('Views', { '</tree>', }); - assert.strictEqual(list.$('tbody td.o_form_invisible').length, 3, + assert.strictEqual(list.$('tbody td.o_invisible_modifier').length, 3, "there should be 3 invisible foo cells in readonly mode"); // Make first line editable list.$('tbody tr:nth(0) td:nth(1)').click(); - assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_form_invisible').length, 1, + assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_invisible_modifier').length, 1, "the foo field widget should have been rendered as invisible"); list.$('tbody tr:nth(0) td:nth(2) input').click(); - assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]:not(.o_form_invisible)').length, 1, + assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]:not(.o_invisible_modifier)').length, 1, "the foo field widget should have been marked as non-invisible"); - assert.strictEqual(list.$('tbody td.o_form_invisible').length, 2, + assert.strictEqual(list.$('tbody td.o_invisible_modifier').length, 2, "the foo field widget parent cell should not be invisible anymore"); list.$('tbody tr:nth(0) td:nth(2) input').click(); - assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_form_invisible').length, 1, + assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_invisible_modifier').length, 1, "the foo field widget should have been marked as invisible again"); - assert.strictEqual(list.$('tbody td.o_form_invisible').length, 3, + assert.strictEqual(list.$('tbody td.o_invisible_modifier').length, 3, "the foo field widget parent cell should now be invisible again"); // Reswitch the cell to editable and save the row list.$('tbody tr:nth(0) td:nth(2) input').click(); list.$('thead').click(); - assert.strictEqual(list.$('tbody td.o_form_invisible').length, 2, + assert.strictEqual(list.$('tbody td.o_invisible_modifier').length, 2, "there should be 2 invisible foo cells in readonly mode"); list.destroy(); @@ -1460,7 +1457,7 @@ QUnit.module('Views', { '</tree>', }); - assert.strictEqual(list.$('tbody td.o_readonly').length, 3, + assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 3, "there should be 3 readonly foo cells in readonly mode"); // Make first line editable @@ -1472,20 +1469,20 @@ QUnit.module('Views', { list.$('tbody tr:nth(0) td:nth(2) input').click(); assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]').length, 1, "the foo field widget should have been rerendered as editable"); - assert.strictEqual(list.$('tbody td.o_readonly').length, 2, + assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 2, "the foo field widget parent cell should not be readonly anymore"); list.$('tbody tr:nth(0) td:nth(2) input').click(); assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > span[name="foo"]').length, 1, "the foo field widget should have been rerendered as readonly"); - assert.strictEqual(list.$('tbody td.o_readonly').length, 3, + assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 3, "the foo field widget parent cell should now be readonly again"); // Reswitch the cell to editable and save the row list.$('tbody tr:nth(0) td:nth(2) input').click(); list.$('thead').click(); - assert.strictEqual(list.$('tbody td.o_readonly').length, 2, + assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 2, "there should be 2 readonly foo cells in readonly mode"); list.destroy(); @@ -1505,32 +1502,32 @@ QUnit.module('Views', { '</tree>', }); - assert.strictEqual(list.$('tbody td.o_form_required').length, 3, + assert.strictEqual(list.$('tbody td.o_required_modifier').length, 3, "there should be 3 required foo cells in readonly mode"); // Make first line editable list.$('tbody tr:nth(0) td:nth(1)').click(); - assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_form_required').length, 1, + assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_required_modifier').length, 1, "the foo field widget should have been rendered as required"); list.$('tbody tr:nth(0) td:nth(2) input').click(); - assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]:not(.o_form_required)').length, 1, + assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]:not(.o_required_modifier)').length, 1, "the foo field widget should have been marked as non-required"); - assert.strictEqual(list.$('tbody td.o_form_required').length, 2, + assert.strictEqual(list.$('tbody td.o_required_modifier').length, 2, "the foo field widget parent cell should not be required anymore"); list.$('tbody tr:nth(0) td:nth(2) input').click(); - assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_form_required').length, 1, + assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"].o_required_modifier').length, 1, "the foo field widget should have been marked as required again"); - assert.strictEqual(list.$('tbody td.o_form_required').length, 3, + assert.strictEqual(list.$('tbody td.o_required_modifier').length, 3, "the foo field widget parent cell should now be required again"); // Reswitch the cell to editable and save the row list.$('tbody tr:nth(0) td:nth(2) input').click(); list.$('thead').click(); - assert.strictEqual(list.$('tbody td.o_form_required').length, 2, + assert.strictEqual(list.$('tbody td.o_required_modifier').length, 2, "there should be 2 required foo cells in readonly mode"); list.destroy(); @@ -1571,7 +1568,7 @@ QUnit.module('Views', { "first line should still be in edition as invalid"); assert.strictEqual(list.$('tbody tr.o_selected_row').length, 1, "no other line should be in edition"); - assert.strictEqual($firstFooTd.find('input.o_form_invalid').length, 1, + assert.strictEqual($firstFooTd.find('input.o_field_invalid').length, 1, "the required field should be marked as invalid"); assert.strictEqual(warnings, 1, "a warning should have been displayed"); |
