summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/core/dom.js41
-rw-r--r--addons/web/static/src/js/fields/abstract_field.js2
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js105
-rw-r--r--addons/web/static/src/js/fields/field_registry.js2
-rw-r--r--addons/web/static/src/js/fields/field_utils.js19
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js37
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js18
-rw-r--r--addons/web/static/src/js/views/form/form_renderer.js45
-rw-r--r--addons/web/static/src/js/views/list/list_editable_renderer.js54
-rw-r--r--addons/web/static/src/js/widgets/switch_company_menu.js4
-rw-r--r--addons/web/static/src/less/animation.less43
-rw-r--r--addons/web/static/src/less/control_panel.less135
-rw-r--r--addons/web/static/src/less/control_panel_layout.less70
-rw-r--r--addons/web/static/src/less/fields.less367
-rw-r--r--addons/web/static/src/less/fields_extra.less58
-rw-r--r--addons/web/static/src/less/form_view.less539
-rw-r--r--addons/web/static/src/less/form_view_extra.less145
-rw-r--r--addons/web/static/src/less/form_view_layout.less373
-rw-r--r--addons/web/static/src/less/form_view_layout_extra.less109
-rw-r--r--addons/web/static/src/less/kanban_view.less7
-rw-r--r--addons/web/static/src/less/list_view.less138
-rw-r--r--addons/web/static/src/less/list_view_extra.less10
-rw-r--r--addons/web/static/src/less/model_field_selector.less2
-rw-r--r--addons/web/static/src/less/navbar.less59
-rw-r--r--addons/web/static/src/less/new_views.less83
-rw-r--r--addons/web/static/src/less/search_view_extra.less3
-rw-r--r--addons/web/static/src/less/switch_company_menu.less6
-rw-r--r--addons/web/static/src/less/tree_view.less50
-rw-r--r--addons/web/static/src/less/utils.less4
-rw-r--r--addons/web/static/src/less/views.less99
-rw-r--r--addons/web/static/src/less/web_calendar.less2
-rw-r--r--addons/web/static/src/less/webclient_extra.less35
-rw-r--r--addons/web/static/src/xml/base.xml224
33 files changed, 1210 insertions, 1678 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="&gt; :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 &amp;&amp; !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>