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/chrome/control_panel.js7
-rw-r--r--addons/web/static/src/js/chrome/menu.js61
-rw-r--r--addons/web/static/src/js/chrome/sidebar.js9
-rw-r--r--addons/web/static/src/js/chrome/user_menu.js2
-rw-r--r--addons/web/static/src/js/chrome/web_client.js6
-rw-r--r--addons/web/static/src/js/core/dialog.js4
-rw-r--r--addons/web/static/src/js/core/dom.js164
-rw-r--r--addons/web/static/src/js/fields/abstract_field.js12
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js37
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js6
-rw-r--r--addons/web/static/src/js/fields/upgrade_fields.js2
-rw-r--r--addons/web/static/src/js/libs/bootstrap.js28
-rw-r--r--addons/web/static/src/js/services/config.js15
-rw-r--r--addons/web/static/src/js/services/crash_manager.js2
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js1
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_renderer.js2
-rw-r--r--addons/web/static/src/js/views/form/form_renderer.js52
-rw-r--r--addons/web/static/src/js/views/graph/graph_controller.js10
-rw-r--r--addons/web/static/src/js/views/graph/graph_renderer.js2
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_column.js2
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_column_progressbar.js10
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_column_quick_create.js2
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_controller.js2
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_record.js7
-rw-r--r--addons/web/static/src/js/views/list/list_renderer.js2
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_controller.js13
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_renderer.js6
-rw-r--r--addons/web/static/src/js/views/search/favorites_menu.js25
-rw-r--r--addons/web/static/src/js/views/search/filters_menu.js4
-rw-r--r--addons/web/static/src/js/views/search/groupby_menu.js8
-rw-r--r--addons/web/static/src/js/views/search/search_inputs.js8
-rw-r--r--addons/web/static/src/js/views/search/search_view.js2
-rw-r--r--addons/web/static/src/js/views/search/search_view_mobile.js2
-rw-r--r--addons/web/static/src/js/views/view_dialogs.js4
-rw-r--r--addons/web/static/src/js/widgets/data_export.js20
-rw-r--r--addons/web/static/src/js/widgets/date_picker.js103
-rw-r--r--addons/web/static/src/js/widgets/debug_manager.js8
-rw-r--r--addons/web/static/src/js/widgets/domain_selector.js2
-rw-r--r--addons/web/static/src/js/widgets/dropdown_menu.js14
-rw-r--r--addons/web/static/src/js/widgets/model_field_selector.js6
-rw-r--r--addons/web/static/src/js/widgets/switch_company_menu.js6
-rw-r--r--addons/web/static/src/scss/animation.scss16
-rw-r--r--addons/web/static/src/scss/base_settings.scss81
-rw-r--r--addons/web/static/src/scss/bootstrap_overridden.scss212
-rw-r--r--addons/web/static/src/scss/bootstrap_overridden_frontend.scss3
-rw-r--r--addons/web/static/src/scss/bs_mixins_overrides.scss38
-rw-r--r--addons/web/static/src/scss/control_panel.scss31
-rw-r--r--addons/web/static/src/scss/data_export.scss34
-rw-r--r--addons/web/static/src/scss/datepicker.scss21
-rw-r--r--addons/web/static/src/scss/domain_selector.scss36
-rw-r--r--addons/web/static/src/scss/dropdown.scss21
-rw-r--r--addons/web/static/src/scss/dropdown_extra.scss6
-rw-r--r--addons/web/static/src/scss/dropdown_menu.scss29
-rw-r--r--addons/web/static/src/scss/fields.scss82
-rw-r--r--addons/web/static/src/scss/fields_extra.scss2
-rw-r--r--addons/web/static/src/scss/form_view.scss96
-rw-r--r--addons/web/static/src/scss/form_view_extra.scss4
-rw-r--r--addons/web/static/src/scss/import_bootstrap.scss1
-rw-r--r--addons/web/static/src/scss/import_bootstrap_part1.scss11
-rw-r--r--addons/web/static/src/scss/import_bootstrap_part2.scss40
-rw-r--r--addons/web/static/src/scss/kanban_column_progressbar.scss30
-rw-r--r--addons/web/static/src/scss/kanban_dashboard.scss42
-rw-r--r--addons/web/static/src/scss/kanban_examples_dialog.scss22
-rw-r--r--addons/web/static/src/scss/kanban_view.scss97
-rw-r--r--addons/web/static/src/scss/kanban_view_mobile.scss6
-rw-r--r--addons/web/static/src/scss/layout_background.scss20
-rw-r--r--addons/web/static/src/scss/layout_boxed.scss22
-rw-r--r--addons/web/static/src/scss/layout_clean.scss22
-rw-r--r--addons/web/static/src/scss/list_view.scss18
-rw-r--r--addons/web/static/src/scss/list_view_extra.scss2
-rw-r--r--addons/web/static/src/scss/modal.scss16
-rw-r--r--addons/web/static/src/scss/model_field_selector.scss28
-rw-r--r--addons/web/static/src/scss/navbar.scss58
-rw-r--r--addons/web/static/src/scss/pivot_view.scss4
-rw-r--r--addons/web/static/src/scss/primary_variables.scss36
-rw-r--r--addons/web/static/src/scss/progress_bar.scss2
-rw-r--r--addons/web/static/src/scss/rainbow.scss64
-rw-r--r--addons/web/static/src/scss/report.scss4
-rw-r--r--addons/web/static/src/scss/search_groupby_menu.scss16
-rw-r--r--addons/web/static/src/scss/search_view.scss45
-rw-r--r--addons/web/static/src/scss/search_view_extra.scss14
-rw-r--r--addons/web/static/src/scss/search_view_mobile.scss6
-rw-r--r--addons/web/static/src/scss/secondary_variables.scss19
-rw-r--r--addons/web/static/src/scss/tooltip.scss4
-rw-r--r--addons/web/static/src/scss/ui.scss10
-rw-r--r--addons/web/static/src/scss/ui_extra.scss10
-rw-r--r--addons/web/static/src/scss/utils.scss215
-rw-r--r--addons/web/static/src/scss/views.scss6
-rw-r--r--addons/web/static/src/scss/web_calendar.scss28
-rw-r--r--addons/web/static/src/scss/webclient.scss36
-rw-r--r--addons/web/static/src/scss/webclient_extra.scss9
-rw-r--r--addons/web/static/src/scss/webclient_layout.scss36
-rw-r--r--addons/web/static/src/xml/base.xml477
-rw-r--r--addons/web/static/src/xml/dialog.xml2
-rw-r--r--addons/web/static/src/xml/kanban.xml40
-rw-r--r--addons/web/static/src/xml/report.xml8
-rw-r--r--addons/web/static/src/xml/web_calendar.xml53
97 files changed, 1493 insertions, 1476 deletions
diff --git a/addons/web/static/src/js/chrome/control_panel.js b/addons/web/static/src/js/chrome/control_panel.js
index 0913b574a3d..fb265390f51 100644
--- a/addons/web/static/src/js/chrome/control_panel.js
+++ b/addons/web/static/src/js/chrome/control_panel.js
@@ -245,11 +245,12 @@ var ControlPanel = Widget.extend({
var self = this;
var is_last = (index === length-1);
var li_content = bc.title && _.escape(bc.title.trim()) || data.noDisplayContent;
- var $bc = $('<li>')
- .append(is_last ? li_content : $('<a>').html(li_content))
+ var $bc = $('<li>', {class: 'breadcrumb-item'})
+ .append(is_last ? li_content : $('<a>', {href: '#'}).html(li_content))
.toggleClass('active', is_last);
if (!is_last) {
- $bc.click(function () {
+ $bc.click(function (ev) {
+ ev.preventDefault();
self.trigger_up('breadcrumb_clicked', {controllerID: bc.controllerID});
});
}
diff --git a/addons/web/static/src/js/chrome/menu.js b/addons/web/static/src/js/chrome/menu.js
index 1e253ba54f7..c96d4b17f8c 100644
--- a/addons/web/static/src/js/chrome/menu.js
+++ b/addons/web/static/src/js/chrome/menu.js
@@ -2,6 +2,7 @@ odoo.define('web.Menu', function (require) {
"use strict";
var core = require('web.core');
+var dom = require('web.dom');
var session = require('web.session');
var Widget = require('web.Widget');
@@ -37,66 +38,10 @@ var Menu = Widget.extend({
}
this.trigger('menu_bound');
- var lazyreflow = _.debounce(this.reflow.bind(this), 200);
- core.bus.on('resize', this, function() {
- if ($(window).width() < 768 ) {
- lazyreflow('all_outside');
- } else {
- lazyreflow();
- }
- });
- core.bus.trigger('resize');
+ dom.initAutoMoreMenu(this.$el);
this.is_bound.resolve();
},
-
- /**
- * Reflow the menu items and dock overflowing items into a "More" menu item.
- * Automatically called when 'menu_bound' event is triggered and on window resizing.
- *
- * @param {string} behavior If set to 'all_outside', all the items are displayed.
- * If not set, only the overflowing items are hidden.
- */
- reflow: function(behavior) {
- var self = this;
- var $more_container = this.$('#menu_more_container').hide();
- var $more = this.$('#menu_more');
- var $systray = this.$el.parents().find('.oe_systray');
-
- $more.children('li').insertBefore($more_container); // Pull all the items out of the more menu
-
- // 'all_outside' beahavior should display all the items, so hide the more menu and exit
- if (behavior === 'all_outside') {
- // Show list of menu items
- self.$el.show();
- this.$el.find('li').show();
- $more_container.hide();
- return;
- }
-
- // Hide all menu items
- var $toplevel_items = this.$el.find('li').not($more_container).not($systray.find('li')).hide();
- // Show list of menu items (which is empty for now since all menu items are hidden)
- self.$el.show();
- $toplevel_items.each(function() {
- var remaining_space = self.$el.parent().width() - $more_container.outerWidth();
- self.$el.parent().children(':visible').each(function() {
- remaining_space -= $(this).outerWidth();
- });
-
- if ($(this).width() >= remaining_space) {
- return false; // the current item will be appended in more_container
- }
- $(this).show(); // show the current item in menu bar
- });
- $more.append($toplevel_items.filter(':hidden').show());
- $more_container.toggle(!!$more.children().length);
- // Hide toplevel item if there is only one
- var $toplevel = self.$el.children("li:visible");
- if ($toplevel.length === 1) {
- $toplevel.hide();
- }
- },
/**
* Opens a given menu by id, as if a user had browsed to that menu by hand
* except does not trigger any event on the way
@@ -143,7 +88,7 @@ var Menu = Widget.extend({
}
// add a tooltip to cropped menu items
this.$secondary_menus.find('.oe_secondary_submenu li a span').each(function() {
- $(this).tooltip(this.scrollWidth > this.clientWidth ? {title: $(this).text().trim(), placement: 'right'} :'destroy');
+ $(this).tooltip(this.scrollWidth > this.clientWidth ? {title: $(this).text().trim(), placement: 'right'} : 'dispose');
});
},
/**
diff --git a/addons/web/static/src/js/chrome/sidebar.js b/addons/web/static/src/js/chrome/sidebar.js
index 47d598aaeb8..d02c936f470 100644
--- a/addons/web/static/src/js/chrome/sidebar.js
+++ b/addons/web/static/src/js/chrome/sidebar.js
@@ -11,7 +11,7 @@ var _t = core._t;
var Sidebar = Widget.extend({
events: {
- "click .dropdown-menu li a": "_onDropdownClicked"
+ "click .dropdown-item": "_onDropdownClicked"
},
/**
* @override
@@ -177,9 +177,10 @@ var Sidebar = Widget.extend({
this.$el.html(QWeb.render('Sidebar', {widget: this}));
// Hides Sidebar sections when item list is empty
- this.$('.o_dropdown').each(function () {
- if (!$(this).find('li').length) {
- $(this).hide();
+ _.each(this.$('.o_dropdown'), function (el) {
+ var $dropdown = $(el);
+ if (!$dropdown.find('.dropdown-item').length) {
+ $dropdown.hide();
}
});
this.$("[title]").tooltip({
diff --git a/addons/web/static/src/js/chrome/user_menu.js b/addons/web/static/src/js/chrome/user_menu.js
index 84c16b51f82..1251c9b6b5b 100644
--- a/addons/web/static/src/js/chrome/user_menu.js
+++ b/addons/web/static/src/js/chrome/user_menu.js
@@ -23,7 +23,7 @@ var UserMenu = Widget.extend({
start: function () {
var self = this;
var session = this.getSession();
- this.$el.on('click', 'li a[data-menu]', function (ev) {
+ this.$el.on('click', '[data-menu]', function (ev) {
ev.preventDefault();
var menu = $(this).data('menu');
self['_onMenu' + menu.charAt(0).toUpperCase() + menu.slice(1)]();
diff --git a/addons/web/static/src/js/chrome/web_client.js b/addons/web/static/src/js/chrome/web_client.js
index c4886cd0e89..d3ebabfab1e 100644
--- a/addons/web/static/src/js/chrome/web_client.js
+++ b/addons/web/static/src/js/chrome/web_client.js
@@ -3,6 +3,7 @@ odoo.define('web.WebClient', function (require) {
var AbstractWebClient = require('web.AbstractWebClient');
var config = require('web.config');
+var core = require('web.core');
var data_manager = require('web.data_manager');
var dom = require('web.dom');
var framework = require('web.framework');
@@ -48,6 +49,9 @@ return AbstractWebClient.extend({
return $.when(systray_menu_loaded, user_menu_loaded).then(function() {
self.menu.start();
self.bind_hashchange();
+ setTimeout(function () {
+ self.menu.$el.removeClass('d-none');
+ }, 200)
});
},
@@ -165,7 +169,7 @@ return AbstractWebClient.extend({
toggle_fullscreen: function(fullscreen) {
this._super(fullscreen);
if (!fullscreen) {
- this.menu.reflow();
+ core.bus.trigger('resize');
}
},
diff --git a/addons/web/static/src/js/core/dialog.js b/addons/web/static/src/js/core/dialog.js
index 847845ae17e..9cca9c1127a 100644
--- a/addons/web/static/src/js/core/dialog.js
+++ b/addons/web/static/src/js/core/dialog.js
@@ -40,7 +40,7 @@ var Dialog = Widget.extend({
* button is added to allow closing the dialog
* @param {string} [options.buttons[].text]
* @param {string} [options.buttons[].classes]
- * Default to 'btn-primary' if only one button, 'btn-default'
+ * Default to 'btn-primary' if only one button, 'btn-secondary'
* otherwise
* @param {boolean} [options.buttons[].close=false]
* @param {function} [options.buttons[].click]
@@ -123,7 +123,7 @@ var Dialog = Widget.extend({
_.each(buttons, function (buttonData) {
var $button = dom.renderButton({
attrs: {
- class: buttonData.classes || (buttons.length > 1 ? 'btn-default' : 'btn-primary'),
+ class: buttonData.classes || (buttons.length > 1 ? 'btn-secondary' : 'btn-primary'),
disabled: buttonData.disabled,
},
icon: buttonData.icon,
diff --git a/addons/web/static/src/js/core/dom.js b/addons/web/static/src/js/core/dom.js
index e82db818bb5..a34a207fda8 100644
--- a/addons/web/static/src/js/core/dom.js
+++ b/addons/web/static/src/js/core/dom.js
@@ -20,6 +20,7 @@ odoo.define('web.dom', function (require) {
* something happens in the DOM.
*/
+var config = require('web.config');
var core = require('web.core');
/**
@@ -208,11 +209,10 @@ return {
* @param {Object} options
* @param {Object} [options.attrs] - Attributes to put on the button element
* @param {string} [options.attrs.type='button']
- * @param {string} [options.attrs.class='btn-default']
+ * @param {string} [options.attrs.class='btn-secondary']
* Note: automatically completed with "btn btn-X"
* (@see options.size for the value of X)
- * @param {string} [options.size='sm'] - @see options.attrs.class
- * Note: use 'md' for no sizing class
+ * @param {string} [options.size] - @see options.attrs.class
* @param {string} [options.icon]
* The specific fa icon class (for example "fa-home") or an URL for
* an image to use as icon.
@@ -235,10 +235,10 @@ return {
}
jQueryParams.class = 'btn';
- if (options.size !== 'md') {
- jQueryParams.class += (' btn-' + (options.size || 'sm'));
+ if (options.size) {
+ jQueryParams.class += (' btn-' + options.size);
}
- jQueryParams.class += (' ' + (extraClasses || 'btn-default'));
+ jQueryParams.class += (' ' + (extraClasses || 'btn-secondary'));
var $button = $('<button/>', jQueryParams);
@@ -262,33 +262,41 @@ return {
return $button;
},
/**
- * Renders a checkbox with standard odoo template. This does not use any xml
- * template to avoid forcing the frontend part to lazy load a xml file for
- * each widget which might want to create a simple checkbox.
+ * Renders a checkbox with standard odoo/BS template. This does not use any
+ * xml template to avoid forcing the frontend part to lazy load a xml file
+ * for each widget which might want to create a simple checkbox.
*
* @param {Object} [options]
* @param {Object} [options.prop]
* Allows to set the input properties (disabled and checked states).
* @param {string} [options.text]
* The checkbox's associated text. If none is given then a simple
- * checkbox without label structure is rendered.
+ * checkbox is rendered.
* @returns {jQuery}
*/
renderCheckbox: function (options) {
- var $container = $('<div class="o_checkbox"><input type="checkbox"/><span/></div>');
- if (options && options.prop) {
- $container.children('input').prop(options.prop);
+ var id = _.uniqueId('checkbox-');
+ var $container = $('<div/>', {
+ class: 'custom-control custom-checkbox',
+ });
+ var $input = $('<input/>', {
+ type: 'checkbox',
+ id: id,
+ class: 'custom-control-input',
+ });
+ var $label = $('<label/>', {
+ for: id,
+ class: 'custom-control-label',
+ text: options && options.text || '',
+ });
+ if (!options || !options.text) {
+ $label.html('&#8203;'); // BS checkboxes need some label content (so
+ // add a zero-width space when there is no text)
}
- if (options && options.text) {
- $container = $('<label/>').append(
- $container,
- $('<span/>', {
- class: 'ml8',
- text: options.text,
- })
- );
+ if (options && options.prop) {
+ $input.prop(options.prop);
}
- return $container;
+ return $container.append($input, $label);
},
/**
* Sets the selection range of a given input or textarea
@@ -308,5 +316,117 @@ return {
.select();
}
},
+ /**
+ * Creates an automatic 'more' dropdown-menu for a set of navbar items.
+ *
+ * @param {jQuery} $el
+ * @param {Object} [options]
+ * @param {string} [options.unfoldable='none']
+ * @param {function} [options.maxWidth]
+ * @param {string} [options.sizeClass='SM']
+ */
+ initAutoMoreMenu: function ($el, options) {
+ options = _.extend({
+ unfoldable: 'none',
+ maxWidth: false,
+ sizeClass: 'SM',
+ }, options || {});
+
+ var $extraItemsToggle = null;
+
+ var debouncedAdapt = _.debounce(_adapt, 250);
+ core.bus.on('resize', null, debouncedAdapt);
+ _adapt();
+
+ $el.data('dom:autoMoreMenu:destroy', function () {
+ _restore();
+ core.bus.off('resize', null, debouncedAdapt);
+ $el.removeData('dom:autoMoreMenu:destroy');
+ });
+
+ function _restore() {
+ if ($extraItemsToggle === null) {
+ return;
+ }
+ var $items = $extraItemsToggle.children('.dropdown-menu').children();
+ $items.addClass('nav-item');
+ $items.children().removeClass('dropdown-item').addClass('nav-link');
+ $items.insertBefore($extraItemsToggle);
+ $extraItemsToggle.remove();
+ $extraItemsToggle = null;
+ }
+
+ function _adapt() {
+ if (!$el.is(':visible')) {
+ return;
+ }
+
+ _restore();
+ if (config.device.size_class <= config.device.SIZES[options.sizeClass]) {
+ return;
+ }
+
+ var $allItems = $el.children();
+ var $unfoldableItems = $allItems.filter(options.unfoldable);
+ var $items = $allItems.not($unfoldableItems);
+
+ var maxWidth = 0;
+ if (options.maxWidth) {
+ maxWidth = options.maxWidth();
+ } else {
+ var rect = $el[0].getBoundingClientRect();
+ var style = window.getComputedStyle($el[0]);
+ maxWidth = (rect.right - rect.left);
+ maxWidth -= (parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth));
+ maxWidth -= _.reduce($unfoldableItems, function (sum, el) {
+ return sum + computeFloatOuterWidthWithMargins(el);
+ }, 0);
+ }
+
+ var nbItems = $items.length;
+ var menuItemsWidth = _.reduce($items, function (sum, el) {
+ return sum + computeFloatOuterWidthWithMargins(el);
+ }, 0);
+
+ if (maxWidth - menuItemsWidth >= -0.001) {
+ return
+ }
+
+ var $dropdownMenu = $('<ul/>', {class: 'dropdown-menu'});
+ $extraItemsToggle = $('<li/>', {class: 'nav-item dropdown o_extra_menu_items'})
+ .append($('<a/>', {href: '#', class: 'nav-link dropdown-toggle o-no-caret', 'data-toggle': 'dropdown'})
+ .append($('<i/>', {class: 'fa fa-plus'})))
+ .append($dropdownMenu);
+ $extraItemsToggle.insertAfter($items.last());
+
+ menuItemsWidth += computeFloatOuterWidthWithMargins($extraItemsToggle[0]);
+ do {
+ menuItemsWidth -= computeFloatOuterWidthWithMargins($items.eq(--nbItems)[0]);
+ } while (menuItemsWidth > maxWidth);
+
+ var $extraItems = $items.slice(nbItems).detach();
+ $extraItems.removeClass('nav-item');
+ $extraItems.children().removeClass('nav-link').addClass('dropdown-item');
+ $dropdownMenu.append($extraItems);
+ $extraItemsToggle.find('.nav-link').toggleClass('active', $extraItems.children().hasClass('active'));
+ }
+
+ function computeFloatOuterWidthWithMargins(el) {
+ var rect = el.getBoundingClientRect();
+ var style = window.getComputedStyle(el);
+ return rect.right - rect.left + parseFloat(style.marginLeft) + parseFloat(style.marginRight);
+ }
+ },
+ /**
+ * Cleans what has been done by `initAutoMoreMenu'.
+ *
+ * @param {jQuery} $el
+ */
+ destroyAutoMoreMenu: function ($el) {
+ var destroyFunc = $el.data('dom:autoMoreMenu:destroy');
+ if (destroyFunc) {
+ destroyFunc.call(null);
+ }
+ },
};
});
diff --git a/addons/web/static/src/js/fields/abstract_field.js b/addons/web/static/src/js/fields/abstract_field.js
index eab0093ed50..7cf72791be5 100644
--- a/addons/web/static/src/js/fields/abstract_field.js
+++ b/addons/web/static/src/js/fields/abstract_field.js
@@ -304,7 +304,6 @@ var AbstractField = Widget.extend({
this._reset(record, event);
return this._render() || $.when();
},
-
/**
* Remove the invalid class on a field
*/
@@ -312,7 +311,15 @@ var AbstractField = Widget.extend({
this.$el.removeClass('o_field_invalid');
this.$el.removeAttr('aria-invalid');
},
-
+ /**
+ * Sets the given id on the focusable element of the field and as 'for'
+ * attribute of potential internal labels.
+ *
+ * @param {string} id
+ */
+ setIDForLabel: function (id) {
+ this.getFocusableElement().attr('id', id);
+ },
/**
* add the invalid class on a field
*/
@@ -320,7 +327,6 @@ var AbstractField = Widget.extend({
this.$el.addClass('o_field_invalid');
this.$el.attr('aria-invalid', 'true');
},
-
/**
* Update the modifiers with the newest value.
* Now this.attrs.modifiersValue can be used consistantly even with
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index 51816220c9f..bd13305df0c 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -701,8 +701,8 @@ var FieldBoolean = AbstractField.extend({
// The formatValue of boolean fields renders HTML elements similar to
// the one rendered by the widget itself. Even though the event might
// have been fired on the non-widget version of this field, we can still
- // test the presence of its o_checkbox class.
- if (activated && options && options.event && $(options.event.target).parents('.o_checkbox').length) {
+ // test the presence of its custom class.
+ if (activated && options && options.event && $(options.event.target).closest('.custom-control.custom-checkbox').length) {
this._setValue(!this.value); // Toggle the checkbox
}
return activated;
@@ -737,6 +737,15 @@ var FieldBoolean = AbstractField.extend({
}
return rendered;
},
+ /**
+ * Associates the 'for' attribute of the internal label.
+ *
+ * @override
+ */
+ setIDForLabel: function (id) {
+ this._super.apply(this, arguments);
+ this.$('.custom-control-label').attr('for', id);
+ },
//--------------------------------------------------------------------------
// Private
@@ -1612,10 +1621,7 @@ var AttachmentImage = AbstractField.extend({
var StateSelectionWidget = AbstractField.extend({
template: 'FormSelection',
events: {
- 'click a': function (e) {
- e.preventDefault();
- },
- 'click li': '_setSelection'
+ 'click .dropdown-item': '_setSelection',
},
supportedFieldTypes: ['selection'],
@@ -1696,13 +1702,12 @@ var StateSelectionWidget = AbstractField.extend({
* @param {MouseEvent} ev
*/
_setSelection: function (ev) {
- var li = $(ev.target).closest('li');
- if (li.length) {
- var value = String(li.data('value'));
- this._setValue(value);
- if (this.mode === 'edit') {
- this._render();
- }
+ ev.preventDefault();
+ var $item = $(ev.currentTarget);
+ var value = String($item.data('value'));
+ this._setValue(value);
+ if (this.mode === 'edit') {
+ this._render();
}
},
});
@@ -1778,7 +1783,7 @@ var LabelSelection = AbstractField.extend({
_render: function () {
this.classes = this.nodeOptions && this.nodeOptions.classes || {};
var labelClass = this.classes[this.value] || 'primary';
- this.$el.addClass('label label-' + labelClass).text(this._formatValue(this.value));
+ this.$el.addClass('badge badge-' + labelClass).text(this._formatValue(this.value));
},
});
@@ -2693,9 +2698,9 @@ var ImageSelection = AbstractField.extend({
var self = this;
this.$el.empty();
_.each(this.nodeOptions, function (val, key) {
- var $container = $('<div>').addClass('col-xs-3 text-center');
+ var $container = $('<div>').addClass('col-3 text-center');
var $img = $('<img>')
- .addClass('img img-responsive img-thumbnail ml16')
+ .addClass('img img-fluid img-thumbnail ml16')
.toggleClass('btn-info', key === self.value)
.attr('src', val.image_link)
.data('key', key);
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index c1c458d1935..ba83de415e7 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -968,7 +968,7 @@ var FieldX2Many = AbstractField.extend({
_renderButtons: function () {
if (!this.isReadonly && this.view.arch.tag === 'kanban') {
this.$buttons = $(qweb.render('KanbanView.buttons', {
- btnClass: 'btn-default',
+ btnClass: 'btn-secondary',
create_text: this.nodeOptions.create_text,
}));
this.$buttons.on('click', 'button.o-kanban-button-new', this._onAddRecord.bind(this));
@@ -1887,7 +1887,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({
this.$color_picker.dropdown('toggle');
this.$color_picker.attr("tabindex", 1).focus();
if (!tagColor) {
- this.$('.o_checkbox input').prop('checked', true);
+ this.$('.custom-checkbox input').prop('checked', true);
}
}
},
@@ -1909,7 +1909,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({
var changes = {};
if ($target.is('.o_hide_in_kanban')) {
- var $checkbox = $('.o_hide_in_kanban .o_checkbox input');
+ var $checkbox = $('.o_hide_in_kanban .custom-checkbox input');
$checkbox.prop('checked', !$checkbox.prop('checked')); // toggle checkbox
this.prevColors = this.prevColors ? this.prevColors : {};
if ($checkbox.is(':checked')) {
diff --git a/addons/web/static/src/js/fields/upgrade_fields.js b/addons/web/static/src/js/fields/upgrade_fields.js
index 119a64881e3..dd91ca2efc2 100644
--- a/addons/web/static/src/js/fields/upgrade_fields.js
+++ b/addons/web/static/src/js/fields/upgrade_fields.js
@@ -94,7 +94,7 @@ var AbstractFieldUpgrade = {
this._super.apply(this, arguments);
this._insertEnterpriseLabel($("<span>", {
text: "Enterprise",
- 'class': "label label-primary oe_inline o_enterprise_label"
+ 'class': "badge badge-primary oe_inline o_enterprise_label"
}));
},
/**
diff --git a/addons/web/static/src/js/libs/bootstrap.js b/addons/web/static/src/js/libs/bootstrap.js
index 04ca2381d7d..135a6b65df6 100644
--- a/addons/web/static/src/js/libs/bootstrap.js
+++ b/addons/web/static/src/js/libs/bootstrap.js
@@ -7,23 +7,19 @@ odoo.define('web.bootstrap.extensions', function () {
*/
/* Bootstrap defaults overwrite */
-$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top';
-$.fn.tooltip.Constructor.DEFAULTS.html = true;
-$.fn.tooltip.Constructor.DEFAULTS.trigger = 'hover focus click';
-$.fn.tooltip.Constructor.DEFAULTS.container = 'body';
-$.fn.tooltip.Constructor.DEFAULTS.delay = { show: 1000, hide: 0 };
-//overwrite bootstrap tooltip method to prevent showing 2 tooltip at the same time
-var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show;
-$.fn.modal.Constructor.prototype.enforceFocus = function () { };
+$.fn.tooltip.Constructor.Default.placement = 'top';
+$.fn.tooltip.Constructor.Default.fallbackPlacement = ['bottom', 'right', 'left', 'top'];
+$.fn.tooltip.Constructor.Default.html = true;
+$.fn.tooltip.Constructor.Default.trigger = 'hover focus click';
+$.fn.tooltip.Constructor.Default.container = 'body';
+$.fn.tooltip.Constructor.Default.delay = { show: 1000, hide: 0 };
+
+var bootstrapShowFunction = $.fn.tooltip.Constructor.prototype.show;
$.fn.tooltip.Constructor.prototype.show = function () {
+ // Overwrite bootstrap tooltip method to prevent showing 2 tooltip at the
+ // same time
$('.tooltip').remove();
- //the following fix the bug when using placement
- //auto and the parent element does not exist anymore resulting in
- //an error. This should be remove once we updade bootstrap to a version that fix the bug
- //edit: bug has been fixed here : https://github.com/twbs/bootstrap/pull/13752
- var e = $.Event('show.bs.' + this.type);
- var inDom = $.contains(document.documentElement, this.$element[0]);
- if (e.isDefaultPrevented() || !inDom) return;
- return bootstrap_show_function.call(this);
+
+ return bootstrapShowFunction.call(this);
};
});
diff --git a/addons/web/static/src/js/services/config.js b/addons/web/static/src/js/services/config.js
index d05a263ef4e..946f7d39f55 100644
--- a/addons/web/static/src/js/services/config.js
+++ b/addons/web/static/src/js/services/config.js
@@ -41,22 +41,23 @@ var config = {
/**
* A frequent use case is to have a different render in 'mobile' mode,
* meaning when the screen is small. This flag (boolean) is true when
- * the size is XXS or XS. It is also updated dynamically.
+ * the size is XS/VSM/SM. It is also updated dynamically.
*
* @type Boolean
*/
isMobile: null,
/**
- * Mapping between the numbers 0,1,2,3,4,5 and some descriptions
+ * Mapping between the numbers 0,1,2,3,4,5,6 and some descriptions
*/
- SIZES: { XXS: 0, XS: 1, SM: 2, MD: 3, LG: 4, XL: 5 },
+ SIZES: { XS: 0, VSM: 1, SM: 2, MD: 3, LG: 4, XL: 5, XXL: 6 },
},
};
var medias = [
window.matchMedia('(max-width: 474px)'),
- window.matchMedia('(min-width: 475px) and (max-width: 767px)'),
+ window.matchMedia('(min-width: 475px) and (max-width: 575px)'),
+ window.matchMedia('(min-width: 576px) and (max-width: 767px)'),
window.matchMedia('(min-width: 768px) and (max-width: 991px)'),
window.matchMedia('(min-width: 992px) and (max-width: 1199px)'),
window.matchMedia('(min-width: 1200px) and (max-width: 1533px)'),
@@ -69,8 +70,8 @@ var medias = [
* @returns {integer} a number between 0 and 5, included
*/
function _getSizeClass() {
- for(var i = 0 ; i < medias.length ; i++) {
- if(medias[i].matches) {
+ for (var i = 0 ; i < medias.length ; i++) {
+ if (medias[i].matches) {
return i;
}
}
@@ -83,7 +84,7 @@ function _updateSizeProps() {
var sc = _getSizeClass();
if (sc !== config.device.size_class) {
config.device.size_class = sc;
- config.device.isMobile = config.device.size_class <= config.device.SIZES.SM;
+ config.device.isMobile = config.device.size_class <= config.device.SIZES.MD;
}
}
diff --git a/addons/web/static/src/js/services/crash_manager.js b/addons/web/static/src/js/services/crash_manager.js
index a5b8cb32c13..b105913464e 100644
--- a/addons/web/static/src/js/services/crash_manager.js
+++ b/addons/web/static/src/js/services/crash_manager.js
@@ -142,7 +142,7 @@ var CrashManager = core.Class.extend({
});
});
dialog.on("closed", this, function () {
- $clipboardBtn.tooltip("destroy");
+ $clipboardBtn.tooltip('dispose');
clipboard.destroy();
});
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 13a00dda046..197892f3361 100644
--- a/addons/web/static/src/js/views/basic/basic_renderer.js
+++ b/addons/web/static/src/js/views/basic/basic_renderer.js
@@ -152,7 +152,6 @@ var BasicRenderer = AbstractRenderer.extend({
// widget's $el
$node = $node.length ? $node : widget.$el;
$node.tooltip({
- delay: { show: 1000, hide: 0 },
title: function () {
return qweb.render('WidgetLabel.tooltip', {
debug: config.debug,
diff --git a/addons/web/static/src/js/views/calendar/calendar_renderer.js b/addons/web/static/src/js/views/calendar/calendar_renderer.js
index 4b4050b67cc..ffb4f41ad6b 100644
--- a/addons/web/static/src/js/views/calendar/calendar_renderer.js
+++ b/addons/web/static/src/js/views/calendar/calendar_renderer.js
@@ -98,7 +98,7 @@ var SidebarFilter = Widget.extend(FieldManagerMixin, {
this.many2one.filter_ids = _.without(_.pluck(this.filters, 'value'), 'all');
}
this.$el.on('click', '.o_remove', this._onFilterRemove.bind(this));
- this.$el.on('click', '.o_checkbox input', this._onFilterActive.bind(this));
+ this.$el.on('click', '.custom-checkbox input', this._onFilterActive.bind(this));
},
//--------------------------------------------------------------------------
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 646dfdd8c40..276173c6f9a 100644
--- a/addons/web/static/src/js/views/form/form_renderer.js
+++ b/addons/web/static/src/js/views/form/form_renderer.js
@@ -35,7 +35,7 @@ var FormRenderer = BasicRenderer.extend({
* @override
*/
start: function () {
- if (config.device.size_class <= config.device.SIZES.XXS) {
+ if (config.device.size_class <= config.device.SIZES.XS) {
this.$el.addClass('o_xxs_form_view');
}
return this._super.apply(this, arguments);
@@ -159,9 +159,9 @@ var FormRenderer = BasicRenderer.extend({
.removeAttr('disabled');
},
/**
- * Put the focus on the last activated widget.
+ * Put the focus on the last activated widget.
* This function is used when closing a dialog to give the focus back to the
- * form that has opened it and ensures that the focus is in the correct
+ * form that has opened it and ensures that the focus is in the correct
* field.
*/
focusLastActivatedWidget: function () {
@@ -181,7 +181,7 @@ var FormRenderer = BasicRenderer.extend({
var $notebook = $(this);
var name = $notebook.data('name');
var index = -1;
- $notebook.find('li').each(function (i) {
+ $notebook.find('.nav-link').each(function (i) {
if ($(this).hasClass('active')) {
index = i;
}
@@ -265,7 +265,6 @@ var FormRenderer = BasicRenderer.extend({
_addButtonTooltip: function (node, $button) {
var self = this;
$button.tooltip({
- delay: { show: 1000, hide: 0 },
title: function () {
return qweb.render('WidgetButton.tooltip', {
debug: config.debug,
@@ -364,11 +363,11 @@ var FormRenderer = BasicRenderer.extend({
text: _t("More"),
}));
- var $ul = $("<ul>", {'class': "dropdown-menu o_dropdown_more", role: "menu"});
+ var $dropdown = $("<div>", {'class': "dropdown-menu o_dropdown_more", role: "menu"});
_.each(folded_buttons, function ($button) {
- $('<li>').appendTo($ul).append($button);
+ $button.addClass('dropdown-item').appendTo($dropdown);
});
- $ul.appendTo($result);
+ $dropdown.appendTo($result);
}
this._handleAttributes($result, node);
@@ -397,12 +396,13 @@ var FormRenderer = BasicRenderer.extend({
// Current API of odoo for rendering buttons is "if classes are given
// use those on top of the 'btn' and 'btn-{size}' classes, otherwise act
- // as if 'btn-default' class was given". The problem is that, for header
- // buttons only, we allowed users to only indicate their custom classes
- // without having to explicitely ask for the 'btn-default' class to be
- // added. We force it so here when no bootstrap btn type class is found.
- if ($button.not('.btn-primary, .btn-default, .btn-link, .btn-success, .btn-info, .btn-warning, .btn-danger').length) {
- $button.addClass('btn-default');
+ // as if 'btn-secondary' class was given". The problem is that, for
+ // header buttons only, we allowed users to only indicate their custom
+ // classes without having to explicitely ask for the 'btn-secondary'
+ // class to be added. We force it so here when no bootstrap btn type
+ // class is found.
+ if ($button.not('.btn-primary, .btn-secondary, .btn-link, .btn-success, .btn-info, .btn-warning, .btn-danger').length) {
+ $button.addClass('btn-secondary');
}
this._addOnClickAction($button, node);
@@ -612,10 +612,11 @@ var FormRenderer = BasicRenderer.extend({
'data-toggle': 'tab',
disable_anchor: 'true',
href: '#' + page_id,
+ class: 'nav-link',
role: 'tab',
text: page.attrs.string,
});
- return $('<li>').append($a);
+ return $('<li>', {class: 'nav-item'}).append($a);
},
/**
* @private
@@ -761,7 +762,7 @@ var FormRenderer = BasicRenderer.extend({
_renderTagNotebook: function (node) {
var self = this;
var $headers = $('<ul class="nav nav-tabs">');
- var $pages = $('<div class="tab-content nav nav-tabs">');
+ var $pages = $('<div class="tab-content">');
var autofocusTab = -1;
// renderedTabs is used to aggregate the generated $headers and $pages
// alongside their node, so that their modifiers can be registered once
@@ -785,7 +786,7 @@ var FormRenderer = BasicRenderer.extend({
});
if (renderedTabs.length) {
var tabToFocus = renderedTabs[Math.max(0, autofocusTab)];
- tabToFocus.$header.addClass('active');
+ tabToFocus.$header.find('.nav-link').addClass('active');
tabToFocus.$page.addClass('active');
}
// register the modifiers for each tab
@@ -793,12 +794,13 @@ var FormRenderer = BasicRenderer.extend({
self._registerModifiers(tab.node, self.state, tab.$header, {
callback: function (element, modifiers) {
// if the active tab is invisible, activate the first visible tab instead
- if (modifiers.invisible && element.$el.hasClass('active')) {
- element.$el.removeClass('active');
+ var $link = element.$el.find('.nav-link');
+ if (modifiers.invisible && $link.hasClass('active')) {
+ $link.removeClass('active');
tab.$page.removeClass('active');
- var $firstVisibleTab = $headers.find('li:not(.o_invisible_modifier):first()');
+ var $firstVisibleTab = $headers.find('li:not(.o_invisible_modifier):first() > a');
$firstVisibleTab.addClass('active');
- $pages.find($firstVisibleTab.find('a').attr('href')).addClass('active');
+ $pages.find($firstVisibleTab.attr('href')).addClass('active');
}
},
});
@@ -859,7 +861,7 @@ var FormRenderer = BasicRenderer.extend({
this.defs = defs;
var $form = this._renderNode(this.arch).addClass(this.className);
delete this.defs;
-
+
return $.when.apply($, defs).then(function () {
self._updateView($form.contents());
}, function () {
@@ -867,7 +869,7 @@ var FormRenderer = BasicRenderer.extend({
}).then(function(){
if (self.lastActivatedFieldIndex >= 0) {
self._activateNextFieldWidget(self.state, self.lastActivatedFieldIndex);
- }
+ }
});
},
/**
@@ -900,7 +902,7 @@ var FormRenderer = BasicRenderer.extend({
// enterprise label will be displayed as many times as the field
// exists on settings.
var $widgets = self.$('.o_field_widget[name=' + widget.name + ']');
- var $label = idForLabel ? self.$('label[for=' + idForLabel + ']') : $();
+ var $label = idForLabel ? self.$('.o_form_label[for=' + idForLabel + ']') : $();
$label = $label.eq($widgets.index(widget.$el));
if (config.debug || widget.attrs.help || widget.field.help) {
self._addFieldTooltip(widget, $label);
@@ -920,7 +922,7 @@ var FormRenderer = BasicRenderer.extend({
* @param {idForLabel} string
*/
_setIDForLabel: function (widget, idForLabel) {
- widget.getFocusableElement().attr('id', idForLabel);
+ widget.setIDForLabel(idForLabel);
},
//--------------------------------------------------------------------------
diff --git a/addons/web/static/src/js/views/graph/graph_controller.js b/addons/web/static/src/js/views/graph/graph_controller.js
index e7f25c23fdd..b6a1c121f0f 100644
--- a/addons/web/static/src/js/views/graph/graph_controller.js
+++ b/addons/web/static/src/js/views/graph/graph_controller.js
@@ -45,7 +45,7 @@ var GraphController = AbstractController.extend(GroupByMenuInterfaceMixin,{
destroy: function () {
if (this.$buttons) {
// remove jquery's tooltip() handlers
- this.$buttons.find('button').off().tooltip('destroy');
+ this.$buttons.find('button').off().tooltip('dispose');
}
this._super.apply(this, arguments);
},
@@ -161,8 +161,9 @@ var GraphController = AbstractController.extend(GroupByMenuInterfaceMixin,{
this.$buttons
.find('.o_graph_button[data-mode="' + state.mode + '"]')
.addClass('active');
- this.$measureList.find('li').each(function (index, li) {
- $(li).toggleClass('selected', $(li).data('field') === state.measure);
+ _.each(this.$measureList.find('.dropdown-item'), function (item) {
+ var $item = $(item);
+ $item.toggleClass('selected', $item.data('field') === state.measure);
});
},
@@ -185,8 +186,7 @@ var GraphController = AbstractController.extend(GroupByMenuInterfaceMixin,{
} else if ($target.parents('.o_graph_measures_list').length) {
event.preventDefault();
event.stopPropagation();
- parent = $target.parent();
- field = parent.data('field');
+ field = $target.data('field');
this._setMeasure(field);
}
},
diff --git a/addons/web/static/src/js/views/graph/graph_renderer.js b/addons/web/static/src/js/views/graph/graph_renderer.js
index 1fbd6572a9a..686bbaee842 100644
--- a/addons/web/static/src/js/views/graph/graph_renderer.js
+++ b/addons/web/static/src/js/views/graph/graph_renderer.js
@@ -243,7 +243,7 @@ return AbstractRenderer.extend({
svg.transition().duration(100);
- var legend_right = config.device.size_class > config.device.SIZES.XS;
+ var legend_right = config.device.size_class > config.device.SIZES.VSM;
var chart = nv.models.pieChart().labelType('percent');
chart.options({
diff --git a/addons/web/static/src/js/views/kanban/kanban_column.js b/addons/web/static/src/js/views/kanban/kanban_column.js
index 95e3f1e85b1..a1c7e415470 100644
--- a/addons/web/static/src/js/views/kanban/kanban_column.js
+++ b/addons/web/static/src/js/views/kanban/kanban_column.js
@@ -153,7 +153,7 @@ var KanbanColumn = Widget.extend({
this.$el.toggleClass('o_column_folded', this.folded && !config.device.isMobile);
var tooltip = this.data.count + _t(' records');
tooltip = '<p>' + tooltip + '</p>' + this.tooltipInfo;
- this.$header.find('.o_kanban_header_title').tooltip({html: true}).attr('data-original-title', tooltip);
+ this.$header.find('.o_kanban_header_title').tooltip({}).attr('data-original-title', tooltip);
if (!this.remaining) {
this.$('.o_kanban_load_more').remove();
} else {
diff --git a/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js b/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js
index 7af6b677dcf..0bfe5027876 100644
--- a/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js
+++ b/addons/web/static/src/js/views/kanban/kanban_column_progressbar.js
@@ -133,9 +133,8 @@ var KanbanColumnProgressBar = Widget.extend({
});
if (this.progressBarHelp && _.every(this.subgroupCounts, function (val) { return val === 0; })) {
this.$el.tooltip({
- delay: '0',
- trigger:'hover',
- placement: 'top',
+ delay: 0,
+ trigger: 'hover',
title: this.progressBarHelp,
});
}
@@ -152,9 +151,8 @@ var KanbanColumnProgressBar = Widget.extend({
// Adapt tooltip
$bar.attr('data-original-title', count + ' ' + key);
$bar.tooltip({
- delay: '0',
- trigger:'hover',
- placement: 'top'
+ delay: 0,
+ trigger: 'hover',
});
// Adapt active state
diff --git a/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js b/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js
index 170b950a49d..b2a38d4e53e 100644
--- a/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js
+++ b/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js
@@ -184,7 +184,7 @@ var ColumnQuickCreate = Widget.extend({
examples: this.examples,
})),
buttons: [{
- classes: 'btn-primary pull-right',
+ classes: 'btn-primary float-right',
close: true,
text: _t('Got it'),
}],
diff --git a/addons/web/static/src/js/views/kanban/kanban_controller.js b/addons/web/static/src/js/views/kanban/kanban_controller.js
index 26846e2c511..ab05fabd517 100644
--- a/addons/web/static/src/js/views/kanban/kanban_controller.js
+++ b/addons/web/static/src/js/views/kanban/kanban_controller.js
@@ -119,7 +119,7 @@ var KanbanController = BasicController.extend({
return this._super.apply(this, arguments);
},
/**
- * In grouped mode, set 'Create' button as btn-default if there is no column
+ * In grouped mode, set 'Create' button as btn-secondary if there is no column
* (except if we can't create new columns)
*
* @private
diff --git a/addons/web/static/src/js/views/kanban/kanban_record.js b/addons/web/static/src/js/views/kanban/kanban_record.js
index 247f8eca90f..627543b3422 100644
--- a/addons/web/static/src/js/views/kanban/kanban_record.js
+++ b/addons/web/static/src/js/views/kanban/kanban_record.js
@@ -99,8 +99,7 @@ var KanbanRecord = Widget.extend({
var tooltip = $el.attr('tooltip');
if (tooltip) {
$el.tooltip({
- 'html': true,
- 'title': self.qweb.render(tooltip, self.qweb_context)
+ title: self.qweb.render(tooltip, self.qweb_context)
});
}
});
@@ -350,7 +349,7 @@ var KanbanRecord = Widget.extend({
_setFieldDisplay: function ($el, fieldName) {
// attribute display
if (this.fieldsInfo[fieldName].display === 'right') {
- $el.addClass('pull-right');
+ $el.addClass('float-right');
} else if (this.fieldsInfo[fieldName].display === 'full') {
$el.addClass('o_text_block');
}
@@ -490,7 +489,7 @@ var KanbanRecord = Widget.extend({
if (elem === event.currentTarget) {
ischild = false;
}
- var test_event = events && events.click && (events.click.length > 1 || events.click[0].namespace !== "tooltip");
+ var test_event = events && events.click && (events.click.length > 1 || events.click[0].namespace !== 'bs.tooltip');
if (ischild) {
children.push(elem);
if (test_event) {
diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js
index 82a08b3b27f..20d68744f6a 100644
--- a/addons/web/static/src/js/views/list/list_renderer.js
+++ b/addons/web/static/src/js/views/list/list_renderer.js
@@ -653,7 +653,7 @@ var ListRenderer = BasicRenderer.extend({
return this._super();
}
- var $table = $('<table>').addClass('o_list_view table table-condensed table-hover table-striped');
+ var $table = $('<table>').addClass('o_list_view table table-sm table-hover table-striped');
this.$el
.addClass('table-responsive')
.append($table);
diff --git a/addons/web/static/src/js/views/pivot/pivot_controller.js b/addons/web/static/src/js/views/pivot/pivot_controller.js
index f0976c9a8b4..945cc132b03 100644
--- a/addons/web/static/src/js/views/pivot/pivot_controller.js
+++ b/addons/web/static/src/js/views/pivot/pivot_controller.js
@@ -164,9 +164,9 @@ var PivotController = AbstractController.extend({
fields: fields
}));
- this.$fieldSelection.find('ul').first()
+ this.$fieldSelection.find('.dropdown-menu').first()
.css({top: top, left: left})
- .show();
+ .addClass('show');
},
/**
* @private
@@ -186,7 +186,7 @@ var PivotController = AbstractController.extend({
var state = this.model.get({raw: true});
_.each(this.measures, function (measure, name) {
var isSelected = _.contains(state.measures, name);
- self.$buttons.find('li[data-field="' + name + '"]')
+ self.$buttons.find('.dropdown-item[data-field="' + name + '"]')
.toggleClass('selected', isSelected);
});
},
@@ -215,8 +215,7 @@ var PivotController = AbstractController.extend({
.then(this.update.bind(this, {}, {reload: false}));
}
if ($target.parents('.o_pivot_measures_list').length) {
- var parent = $target.parent();
- var field = parent.data('field');
+ var field = $target.data('field');
event.preventDefault();
event.stopPropagation();
this.model
@@ -298,11 +297,11 @@ var PivotController = AbstractController.extend({
_onFieldMenuSelection: function (event) {
event.preventDefault();
var $target = $(event.target);
- if ($target.parent().hasClass('disabled')) {
+ if ($target.hasClass('disabled')) {
event.stopPropagation();
return;
}
- var field = $target.parent().data('field');
+ var field = $target.data('field');
var interval = $target.data('interval');
var header = this.model.getHeader(this.lastHeaderSelected);
if (interval) {
diff --git a/addons/web/static/src/js/views/pivot/pivot_renderer.js b/addons/web/static/src/js/views/pivot/pivot_renderer.js
index b3953076161..9312b27f1ef 100644
--- a/addons/web/static/src/js/views/pivot/pivot_renderer.js
+++ b/addons/web/static/src/js/views/pivot/pivot_renderer.js
@@ -9,7 +9,7 @@ var QWeb = core.qweb;
var PivotRenderer = AbstractRenderer.extend({
tagName: 'table',
- className: 'table-hover table-condensed table-bordered',
+ className: 'table-hover table-sm table-bordered',
events: _.extend({}, AbstractRenderer.prototype.events, {
'hover td': '_onTdHover',
}),
@@ -105,7 +105,7 @@ var PivotRenderer = AbstractRenderer.extend({
}
$row.append($cell);
- $cell.toggleClass('hidden-xs', (cell.expanded !== undefined) || (cell.measure !== undefined && j < headers[i].length - this.state.measures.length));
+ $cell.toggleClass('d-none d-md-table-cell', (cell.expanded !== undefined) || (cell.measure !== undefined && j < headers[i].length - this.state.measures.length));
if (cell.height > 1) {
$cell.css('padding', 0);
}
@@ -159,7 +159,7 @@ var PivotRenderer = AbstractRenderer.extend({
}
$row.append($cell);
- $cell.toggleClass('hidden-xs', j < length - nbrMeasures);
+ $cell.toggleClass('d-none d-md-table-cell', j < length - nbrMeasures);
}
$tbody.append($row);
}
diff --git a/addons/web/static/src/js/views/search/favorites_menu.js b/addons/web/static/src/js/views/search/favorites_menu.js
index 1e62ffb5ce3..47e99aec573 100644
--- a/addons/web/static/src/js/views/search/favorites_menu.js
+++ b/addons/web/static/src/js/views/search/favorites_menu.js
@@ -14,14 +14,11 @@ var _t = core._t;
return Widget.extend({
template: 'SearchView.FavoriteMenu',
events: {
- 'click li': function (event) {
- event.stopImmediatePropagation();
+ 'click .dropdown-item': function (ev) {
+ ev.preventDefault();
},
- 'click li a': function (event) {
- event.preventDefault();
- },
- 'click .o_save_search a': function (event) {
- event.preventDefault();
+ 'click .o_save_search': function (ev) {
+ ev.preventDefault();
this.toggle_save_menu();
},
'click .o_save_name button': 'save_favorite',
@@ -49,8 +46,8 @@ return Widget.extend({
this.$save_search = this.$('.o_save_search');
this.$save_name = this.$('.o_save_name');
this.$inputs = this.$save_name.find('input');
- this.$user_divider = this.$('.divider.user_filter');
- this.$shared_divider = this.$('.divider.shared_filter');
+ this.$user_divider = this.$('.dropdown-divider.user_filter');
+ this.$shared_divider = this.$('.dropdown-divider.shared_filter');
this.$inputs.eq(0).val(this.searchview.get_title());
var $shared_filter = this.$inputs.eq(1),
$default_filter = this.$inputs.eq(2);
@@ -207,7 +204,7 @@ return Widget.extend({
};
},
clear_selection: function () {
- this.$('li.selected').removeClass('selected');
+ this.$('.selected').removeClass('selected');
},
/**
* Adds a filter description to the filters dict
@@ -230,10 +227,10 @@ return Widget.extend({
this.$shared_divider.show();
}
if (!(key in this.$filters)) {
- var $filter = $('<li>')
+ var $filter = $('<div>', {class: 'position-relative'})
.addClass(filter.user_id ? 'o-searchview-custom-private'
: 'o-searchview-custom-public')
- .append($('<a>', {'href': '#'}).text(filter.name))
+ .append($('<a>', {href: '#', class: 'dropdown-item'}).text(filter.name))
.append($('<span>', {
class: 'fa fa-trash-o o-remove-filter',
on: {
@@ -256,7 +253,7 @@ return Widget.extend({
});
if (current) {
this.query.remove(current);
- this.$filters[this.key_for(filter)].removeClass('selected');
+ this.$filters[this.key_for(filter)].find('.dropdown-item').removeClass('selected');
return;
}
this.query.reset([this.facet_for(filter)], {
@@ -268,7 +265,7 @@ return Widget.extend({
this.searchview.dataset.set_sort(sort_items);
}
- this.$filters[this.key_for(filter)].addClass('selected');
+ this.$filters[this.key_for(filter)].find('.dropdown-item').addClass('selected');
},
remove_filter: function (filter, $filter, key) {
var self = this;
diff --git a/addons/web/static/src/js/views/search/filters_menu.js b/addons/web/static/src/js/views/search/filters_menu.js
index 221f98faa97..af5425ec2d7 100644
--- a/addons/web/static/src/js/views/search/filters_menu.js
+++ b/addons/web/static/src/js/views/search/filters_menu.js
@@ -76,7 +76,7 @@ var FiltersMenu = DropdownMenu.extend({
category: 'filterCategory',
title: 'Filters',
icon: 'fa fa-filter',
- symbol: this.isMobile ? 'fa fa-chevron-right pull-right mt4' : 'caret'
+ symbol: this.isMobile ? 'fa fa-chevron-right float-right mt4' : false,
};
this._super(parent, dropdownHeader, filters, this.fields);
},
@@ -88,7 +88,7 @@ var FiltersMenu = DropdownMenu.extend({
* @private
*/
start: function () {
- this.$menu = this.$('ul.o_dropdown_menu');
+ this.$menu = this.$('.o_dropdown_menu');
this.$menu.addClass('o_filters_menu');
var generatorMenu = QWeb.render('FiltersMenuGenerator', {widget: this});
this.$menu.append(generatorMenu);
diff --git a/addons/web/static/src/js/views/search/groupby_menu.js b/addons/web/static/src/js/views/search/groupby_menu.js
index 7b3b8e31fef..d686a4d55cb 100644
--- a/addons/web/static/src/js/views/search/groupby_menu.js
+++ b/addons/web/static/src/js/views/search/groupby_menu.js
@@ -14,7 +14,7 @@ var DEFAULT_INTERVAL = 'month';
var GroupByMenu = DropdownMenu.extend({
events: _.extend({}, DropdownMenu.prototype.events,
{
- 'click .o_add_custom_group a': '_onAddCustomGroupClick',
+ 'click .o_add_custom_group': '_onAddCustomGroupClick',
'click button.o_apply_group': '_onButtonApplyClick',
'click .o_group_selector': '_onGroupSelectorClick',
}),
@@ -78,14 +78,14 @@ var GroupByMenu = DropdownMenu.extend({
if (options && options.headerStyle === 'primary') {
style = {
el: {class: 'btn-group o_graph_groupbys_menu o_dropdown', attrs: {'role': 'group'}},
- mainButton: {class: 'btn btn-primary btn-sm dropdown-toggle'},
+ mainButton: {class: 'btn btn-primary dropdown-toggle'},
};
}
var dropdownHeader = {
category: 'groupByCategory',
title: 'Group By',
icon: 'fa fa-bars',
- symbol: this.isMobile ? 'fa fa-chevron-right pull-right mt4' : 'caret',
+ symbol: this.isMobile ? 'fa fa-chevron-right float-right mt4' : false,
style: style,
};
this._super(parent, dropdownHeader, groupbys, options);
@@ -98,7 +98,7 @@ var GroupByMenu = DropdownMenu.extend({
* @private
*/
start: function () {
- this.$menu = this.$('ul.o_dropdown_menu');
+ this.$menu = this.$('.o_dropdown_menu');
this.$menu.addClass('o_group_by_menu');
var $generatorMenu = QWeb.render('GroupbyMenuGenerator', {widget: this});
this.$menu.append($generatorMenu);
diff --git a/addons/web/static/src/js/views/search/search_inputs.js b/addons/web/static/src/js/views/search/search_inputs.js
index ee179d7da74..81f53ee4053 100644
--- a/addons/web/static/src/js/views/search/search_inputs.js
+++ b/addons/web/static/src/js/views/search/search_inputs.js
@@ -503,8 +503,13 @@ var ManyToOneField = CharField.extend({
var FilterGroup = Input.extend(/** @lends instance.web.search.FilterGroup# */{
template: 'SearchView.filters',
+ events: {
+ click: 'toggle_filter',
+ },
+
icon: "fa-filter",
completion_label: _lt("Filter on: %s"),
+
/**
* Inclusive group of filters, creates a continuous "button" with clickable
* sections (the normal display for filters is to be a self-contained button)
@@ -536,7 +541,6 @@ var FilterGroup = Input.extend(/** @lends instance.web.search.FilterGroup# */{
this.searchview.query.on('add remove change reset', this.proxy('search_change'));
},
start: function () {
- this.$el.on('click', 'a', this.proxy('toggle_filter'));
return $.when(null);
},
/**
@@ -684,7 +688,7 @@ var FilterGroup = Input.extend(/** @lends instance.web.search.FilterGroup# */{
toggle_filter: function (e) {
e.preventDefault();
e.stopPropagation();
- this.toggle(this.filters[Number($(e.target).parent().data('index'))]);
+ this.toggle(this.filters[Number($(e.currentTarget).data('index'))]);
},
toggle: function (filter, options) {
this.searchview.query.toggle(this.make_facet([this.make_value(filter)]), options);
diff --git a/addons/web/static/src/js/views/search/search_view.js b/addons/web/static/src/js/views/search/search_view.js
index 9e1f70fec22..2bac31ed27f 100644
--- a/addons/web/static/src/js/views/search/search_view.js
+++ b/addons/web/static/src/js/views/search/search_view.js
@@ -535,7 +535,7 @@ var SearchView = Widget.extend({
* puts the focus on the search input
*/
_focusInput: function () {
- if (!config.device.touch && config.device.size_class >= config.device.SIZES.SM) {
+ if (!config.device.touch && config.device.size_class >= config.device.SIZES.MD) {
this.$('input').focus();
}
},
diff --git a/addons/web/static/src/js/views/search/search_view_mobile.js b/addons/web/static/src/js/views/search/search_view_mobile.js
index 852a65c0a37..ea7fe33ad81 100644
--- a/addons/web/static/src/js/views/search/search_view_mobile.js
+++ b/addons/web/static/src/js/views/search/search_view_mobile.js
@@ -54,7 +54,7 @@ SearchView.include({
* @private
*/
_toggleMobileSearchView: function () {
- this.$('.o_enable_searchview').toggleClass('btn-default', !!this.query.length);
+ this.$('.o_enable_searchview').toggleClass('btn-secondary', !!this.query.length);
this.$('.o_mobile_search').toggleClass('o_hidden');
},
diff --git a/addons/web/static/src/js/views/view_dialogs.js b/addons/web/static/src/js/views/view_dialogs.js
index ed0adf0ff3b..e99f81ccb08 100644
--- a/addons/web/static/src/js/views/view_dialogs.js
+++ b/addons/web/static/src/js/views/view_dialogs.js
@@ -109,7 +109,7 @@ var FormViewDialog = ViewDialog.extend({
options = options || {};
options.buttons = [{
text: (readonly ? _t("Close") : _t("Discard")),
- classes: "btn-default o_form_button_cancel",
+ classes: "btn-secondary o_form_button_cancel",
close: true,
click: function () {
if (!readonly) {
@@ -360,7 +360,7 @@ var SelectCreateDialog = ViewDialog.extend({
// Set the dialog's buttons
self.__buttons = [{
text: _t("Cancel"),
- classes: "btn-default o_form_button_cancel",
+ classes: "btn-secondary o_form_button_cancel",
close: true,
}];
if (!self.options.no_create) {
diff --git a/addons/web/static/src/js/widgets/data_export.js b/addons/web/static/src/js/widgets/data_export.js
index 30e17604077..d05bf2d33fc 100644
--- a/addons/web/static/src/js/widgets/data_export.js
+++ b/addons/web/static/src/js/widgets/data_export.js
@@ -49,7 +49,7 @@ var DataExport = Dialog.extend({
function process_children() {
var $this = $(this);
- if($this.hasClass('open')) {
+ if($this.hasClass('show')) {
$this.children('.o_export_tree_item')
.addClass('o_selected')
.each(process_children);
@@ -77,19 +77,19 @@ var DataExport = Dialog.extend({
switch(e.keyCode || e.which) {
case $.ui.keyCode.LEFT:
- if ($elem.hasClass('open')) {
+ if ($elem.hasClass('show')) {
this.on_expand_action(record);
}
break;
case $.ui.keyCode.RIGHT:
- if (!$elem.hasClass('open')) {
+ if (!$elem.hasClass('show')) {
this.on_expand_action(record);
}
break;
case $.ui.keyCode.UP:
var $prev = $elem.prev('.o_export_tree_item');
if($prev.length === 1) {
- while($prev.hasClass('open')) {
+ while($prev.hasClass('show')) {
$prev = $prev.children('.o_export_tree_item').last();
}
} else {
@@ -104,7 +104,7 @@ var DataExport = Dialog.extend({
break;
case $.ui.keyCode.DOWN:
var $next;
- if($elem.hasClass('open')) {
+ if($elem.hasClass('show')) {
$next = $elem.children('.o_export_tree_item').first();
} else {
$next = $elem.next('.o_export_tree_item');
@@ -408,7 +408,7 @@ var DataExport = Dialog.extend({
var self = this;
if(expansion) {
this.$('.o_export_tree_item[data-id="' + expansion + '"]')
- .addClass('open')
+ .addClass('show')
.find('.o_expand_parent')
.toggleClass('fa-chevron-right fa-chevron-down')
.next()
@@ -429,8 +429,8 @@ var DataExport = Dialog.extend({
},
show_content: function(id) {
var $this = this.$('.o_export_tree_item[data-id="' + id + '"]');
- $this.toggleClass('open');
- var is_open = $this.hasClass('open');
+ $this.toggleClass('show');
+ var is_open = $this.hasClass('show');
$this.children('.o_expand_parent').toggleClass('fa-chevron-down', !!is_open).toggleClass('fa-chevron-right', !is_open);
@@ -441,8 +441,8 @@ var DataExport = Dialog.extend({
if(!is_open) {
$child.hide();
} else if(child_len === $child_field.eq(i).data('id').split("/").length) {
- if ($child.hasClass('open')) {
- $child.removeClass('open');
+ if ($child.hasClass('show')) {
+ $child.removeClass('show');
$child.children('.o_expand_parent').removeClass('fa-chevron-down').addClass('fa-chevron-right');
}
$child.show();
diff --git a/addons/web/static/src/js/widgets/date_picker.js b/addons/web/static/src/js/widgets/date_picker.js
index 8f87b36c874..9d47e79f6a7 100644
--- a/addons/web/static/src/js/widgets/date_picker.js
+++ b/addons/web/static/src/js/widgets/date_picker.js
@@ -1,69 +1,74 @@
odoo.define('web.datepicker', function (require) {
"use strict";
-var core = require('web.core');
var field_utils = require('web.field_utils');
var time = require('web.time');
var Widget = require('web.Widget');
-var _t = core._t;
-
var DateWidget = Widget.extend({
template: "web.datepicker",
type_of_date: "date",
events: {
- 'dp.change': 'changeDatetime',
- 'dp.show': '_onShow',
+ 'change.datetimepicker': 'changeDatetime',
+ 'show.datetimepicker': '_onShow',
+ 'click input.o_datepicker_input': '_onClick',
'change .o_datepicker_input': 'changeDatetime',
+ 'input input': '_onInput',
},
/**
* @override
*/
- init: function(parent, options) {
+ init: function (parent, options) {
this._super.apply(this, arguments);
- var l10n = _t.database.parameters;
-
this.name = parent.name;
- this.options = _.defaults(options || {}, {
+ this.options = _.extend({
format : this.type_of_date === 'datetime' ? time.getLangDatetimeFormat() : time.getLangDateFormat(),
minDate: moment({ y: 1900 }),
maxDate: moment().add(200, "y"),
- calendarWeeks: true,
+ useCurrent: false,
icons: {
time: 'fa fa-clock-o',
date: 'fa fa-calendar',
- next: 'fa fa-chevron-right',
- previous: 'fa fa-chevron-left',
up: 'fa fa-chevron-up',
down: 'fa fa-chevron-down',
- close: 'fa fa-times',
+ previous: 'fa fa-chevron-left',
+ next: 'fa fa-chevron-right',
+ today: 'fa fa-calendar-check-o',
+ clear: 'fa fa-delete',
+ close: 'fa fa-times'
+ },
+ calendarWeeks: true,
+ buttons: {
+ showToday: false,
+ showClear: false,
+ showClose: false,
},
- locale : moment.locale(),
- allowInputToggle: true,
- keyBinds: null,
widgetParent: 'body',
- useCurrent: false,
- });
+ keyBinds: null,
+ allowInputToggle: true,
+ }, options || {});
},
/**
* @override
*/
- start: function() {
+ start: function () {
this.$input = this.$('input.o_datepicker_input');
- this.$input.focus(function(e) {
+ this.$input.focus(function (e) {
e.stopImmediatePropagation();
});
+ this.__libInput = true;
this.$input.datetimepicker(this.options);
- this.picker = this.$input.data('DateTimePicker');
- this.$input.click(this.picker.toggle.bind(this.picker));
+ this.__libInput = false;
this._setReadonly(false);
},
/**
* @override
*/
- destroy: function() {
- this.picker.destroy();
+ destroy: function () {
+ this.__libInput = true;
+ this.$input.datetimepicker('destroy');
+ this.__libInput = false;
this._super.apply(this, arguments);
},
@@ -82,7 +87,7 @@ var DateWidget = Widget.extend({
var hasChanged = !oldValue !== !newValue;
if (oldValue && newValue) {
var formattedOldValue = oldValue.format(time.getLangDatetimeFormat());
- var formattedNewValue = newValue.format(time.getLangDatetimeFormat())
+ var formattedNewValue = newValue.format(time.getLangDatetimeFormat());
if (formattedNewValue !== formattedOldValue) {
hasChanged = true;
}
@@ -106,13 +111,13 @@ var DateWidget = Widget.extend({
*/
isValid: function () {
var value = this.$input.val();
- if(value === "") {
+ if (value === "") {
return true;
} else {
try {
this._parseClient(value);
return true;
- } catch(e) {
+ } catch (e) {
return false;
}
}
@@ -124,9 +129,9 @@ var DateWidget = Widget.extend({
this.set({'value': value});
var formatted_value = value ? this._formatClient(value) : null;
this.$input.val(formatted_value);
- if (this.picker) {
- this.picker.date(value || null);
- }
+ this.__libInput = true;
+ this.$input.datetimepicker('date', value || null);
+ this.__libInput = false;
},
//--------------------------------------------------------------------------
@@ -162,7 +167,7 @@ var DateWidget = Widget.extend({
*
* @private
*/
- _setValueFromUi: function() {
+ _setValueFromUi: function () {
var value = this.$input.val() || false;
this.setValue(this._parseClient(value));
},
@@ -172,6 +177,23 @@ var DateWidget = Widget.extend({
//--------------------------------------------------------------------------
/**
+ * @private
+ */
+ _onClick: function () {
+ this.__libInput = true;
+ this.$input.datetimepicker('toggle');
+ this.__libInput = false;
+ },
+ /**
+ * @private
+ * @param {Event} ev
+ */
+ _onInput: function (ev) {
+ if (this.__libInput) {
+ ev.stopImmediatePropagation();
+ }
+ },
+ /**
* set the date of the picker by the current date or the today date
*
* @private
@@ -179,9 +201,11 @@ var DateWidget = Widget.extend({
_onShow: function () {
//when opening datetimepicker the date and time by default should be the one from
//the input field if any or the current day otherwise
- if(this.$input.val().length !== 0 && this.isValid()) {
+ if (this.$input.val().length !== 0 && this.isValid()) {
var value = this._parseClient(this.$input.val());
- this.picker.date(value);
+ this.__libInput = true;
+ this.$input.datetimepicker('date', value);
+ this.__libInput = false;
this.$input.select();
}
},
@@ -189,11 +213,14 @@ var DateWidget = Widget.extend({
var DateTimeWidget = DateWidget.extend({
type_of_date: "datetime",
- init: function() {
- this._super.apply(this, arguments);
- this.options = _.defaults(this.options, {
- showClose: true,
- });
+ init: function (parent, options) {
+ this._super(parent, _.extend({
+ buttons: {
+ showToday: false,
+ showClear: false,
+ showClose: true,
+ },
+ }, options || {}));
},
});
diff --git a/addons/web/static/src/js/widgets/debug_manager.js b/addons/web/static/src/js/widgets/debug_manager.js
index 4eee9266594..d553387f153 100644
--- a/addons/web/static/src/js/widgets/debug_manager.js
+++ b/addons/web/static/src/js/widgets/debug_manager.js
@@ -23,12 +23,12 @@ var DebugManager = Widget.extend({
template: "WebClient.DebugManager",
events: {
"click a[data-action]": "perform_callback",
- "mouseover .o_debug_dropdowns > li:not(.open)": function(e) {
+ "mouseover .o_debug_dropdowns > li:not(.show)": function(e) {
// Open other dropdowns on mouseover
- var $opened = this.$('.o_debug_dropdowns > li.open');
+ var $opened = this.$('.o_debug_dropdowns > li.show');
if($opened.length) {
- $opened.removeClass('open');
- $(e.currentTarget).addClass('open').find('> a').focus();
+ $opened.removeClass('show');
+ $(e.currentTarget).addClass('show').find('> a').focus();
}
},
},
diff --git a/addons/web/static/src/js/widgets/domain_selector.js b/addons/web/static/src/js/widgets/domain_selector.js
index c5a561b1b77..dab0c97108b 100644
--- a/addons/web/static/src/js/widgets/domain_selector.js
+++ b/addons/web/static/src/js/widgets/domain_selector.js
@@ -161,7 +161,7 @@ var DomainNode = Widget.extend({
var DomainTree = DomainNode.extend({
template: "DomainTree",
events: _.extend({}, DomainNode.prototype.events, {
- "click .o_domain_tree_operator_selector > ul > li > a": "_onOperatorChange",
+ "click .o_domain_tree_operator_selector .dropdown-item": "_onOperatorChange",
}),
custom_events: {
// If a domain child sends a request to add a child or remove one, call
diff --git a/addons/web/static/src/js/widgets/dropdown_menu.js b/addons/web/static/src/js/widgets/dropdown_menu.js
index a3a83519678..6f8f78a13d5 100644
--- a/addons/web/static/src/js/widgets/dropdown_menu.js
+++ b/addons/web/static/src/js/widgets/dropdown_menu.js
@@ -11,8 +11,8 @@ var QWeb = core.qweb;
var DropdownMenu = Widget.extend({
template: 'web.DropdownMenu',
events: {
- 'click li.o_menu_item': '_onItemClick',
- 'click li.o_item_option': '_onOptionClick',
+ 'click .o_menu_item': '_onItemClick',
+ 'click .o_item_option': '_onOptionClick',
'click span.o_trash_button': '_onTrashClick',
'hidden.bs.dropdown': '_onBootstrapClose',
},
@@ -44,12 +44,12 @@ var DropdownMenu = Widget.extend({
this.dropdownCategory = dropdownHeader.category;
this.dropdownTitle = dropdownHeader.title;
this.dropdownIcon = dropdownHeader.icon;
- this.dropdownSymbol = dropdownHeader.symbol || 'caret';
+ this.dropdownSymbol = dropdownHeader.symbol || false;
// this parameter fixes the menu style. By default,
// the style used is the one used in the search view
this.dropdownStyle = dropdownHeader.style || {
el: {class: 'btn-group o_dropdown', attrs: {}},
- mainButton: {class: 'o_dropdown_toggler_btn btn btn-sm btn-default dropdown-toggle'},
+ mainButton: {class: 'o_dropdown_toggler_btn btn btn-secondary dropdown-toggle' + (this.dropdownSymbol ? ' o-no-caret' : '')},
};
this.items = items;
_.each(this.items, this._prepareItem.bind(this));
@@ -105,8 +105,8 @@ var DropdownMenu = Widget.extend({
*/
_renderMenuItems: function () {
var newMenuItems = QWeb.render('DropdownMenu.MenuItems', {widget: this});
- this.$el.find('.o_menu_item,.divider[data-removable="1"]').remove();
- this.$('ul.o_dropdown_menu').prepend($(newMenuItems));
+ this.$el.find('.o_menu_item, .dropdown-divider[data-removable="1"]').remove();
+ this.$('.o_dropdown_menu').prepend($(newMenuItems));
},
/**
* this function computes some default values for some of the item keys
@@ -189,7 +189,7 @@ var DropdownMenu = Widget.extend({
* @param {jQueryEvent} event
*/
_onBootstrapClose: function () {
- _.each(this.items, function(item) {
+ _.each(this.items, function (item) {
item.isOpen = false;
});
this._renderMenuItems();
diff --git a/addons/web/static/src/js/widgets/model_field_selector.js b/addons/web/static/src/js/widgets/model_field_selector.js
index 81abfbe0d6c..e9990ac5105 100644
--- a/addons/web/static/src/js/widgets/model_field_selector.js
+++ b/addons/web/static/src/js/widgets/model_field_selector.js
@@ -253,7 +253,7 @@ var ModelFieldSelector = Widget.extend({
if (!this._isOpen) return;
this._isOpen = false;
- this.$popover.addClass("hidden");
+ this.$popover.addClass('d-none');
if (this.dirty) {
this.dirty = false;
@@ -332,7 +332,7 @@ var ModelFieldSelector = Widget.extend({
}));
// Toggle the warning message
- this.$valid.toggleClass("hidden", !!this.isValid());
+ this.$valid.toggleClass('d-none', !!this.isValid());
// Adapt the popover content
var page = _.last(this.pages);
@@ -376,7 +376,7 @@ var ModelFieldSelector = Widget.extend({
if (this._isOpen) return;
this._isOpen = true;
- this.$popover.removeClass("hidden");
+ this.$popover.removeClass('d-none');
},
/**
* Toggles the valid status of the widget and display the error message if
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 01c224370d2..c9498950a04 100644
--- a/addons/web/static/src/js/widgets/switch_company_menu.js
+++ b/addons/web/static/src/js/widgets/switch_company_menu.js
@@ -18,7 +18,7 @@ var _t = core._t;
var SwitchCompanyMenu = Widget.extend({
template: 'SwitchCompanyMenu',
events: {
- 'click .dropdown-menu li a[data-menu]': '_onClick',
+ 'click .dropdown-item[data-menu]': '_onClick',
},
/**
* @override
@@ -53,8 +53,8 @@ var SwitchCompanyMenu = Widget.extend({
} else {
a = '<span style="margin-right: 24px;"/>';
}
- companiesList += '<li><a href="#" data-menu="company" data-company-id="' +
- company[0] + '">' + a + company[1] + '</a></li>';
+ companiesList += '<a href="#" class="dropdown-item" data-menu="company" data-company-id="' +
+ company[0] + '">' + a + company[1] + '</a>';
});
this.$('.dropdown-menu').html(companiesList);
return this._super();
diff --git a/addons/web/static/src/scss/animation.scss b/addons/web/static/src/scss/animation.scss
index 92097a23298..d65a509bcad 100644
--- a/addons/web/static/src/scss/animation.scss
+++ b/addons/web/static/src/scss/animation.scss
@@ -144,19 +144,3 @@
transform: scale3d(1, 1, 1);
}
}
-
-/************** MIXINS for ANIMATIONS **************/
-@mixin o-display-marked($content, $top, $left, $color) {
- @include o-position-absolute($top: $top, $left: $left);
- font-size: 300px;
- font-family: "FontAwesome";
- content: $content;
- color: $color;
- @include o-transform-origin;
- @include o-animation(markAnim, 1s, ease-in-out, 0s, 1, normal, forwards);
-
- @media (max-width: $screen-sm-max) {
- left: 40%;
- font-size: 30vw;
- }
-}
diff --git a/addons/web/static/src/scss/base_settings.scss b/addons/web/static/src/scss/base_settings.scss
index 7cd25c7e578..436298872da 100644
--- a/addons/web/static/src/scss/base_settings.scss
+++ b/addons/web/static/src/scss/base_settings.scss
@@ -1,16 +1,16 @@
// MIXINS
-@mixin o-base-settings-horizontal-padding($padding-base: $padding-small-vertical) {
+@mixin o-base-settings-horizontal-padding($padding-base: $input-btn-padding-y-sm) {
padding: $padding-base $o-horizontal-padding;
- @media (min-width: $screen-lg-min) {
+ @include media-breakpoint-up(xl) {
padding-left: $o-horizontal-padding*2;;
}
}
// Use a very specif selector to overwrite generic form-view rules
.o_form_view.o_form_nosheet.o_base_settings {
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
+ display: flex;
+ flex-flow: column nowrap;
padding: 0px;
}
@@ -18,20 +18,20 @@
.o_base_settings {
height: 100%;
- @media (max-width: $screen-xs-max) {
- @include o-flex-flow(column, nowrap);
+ @include media-breakpoint-down(sm) {
+ flex-flow: column nowrap;
}
.o_control_panel {
.o_panel {
- @include o-flex-display;
- @include o-flex-flow(row, wrap);
+ display: flex;
+ flex-flow: row wrap;
margin-bottom: $o-sheet-vpadding*0.5;
width: 100%;
.title, .o_setting_search {
- @include o-flex(1, 0, auto);
- width: $screen-xs-min*0.5;
+ flex: 1 0 auto;
+ width: map-get($o-extra-grid-breakpoints, vsm) / 2;
}
.o_setting_search {
@@ -41,15 +41,15 @@
height: 28px;
padding: 0px;
border: 0px;
- border-bottom: 1px solid $gray-lighter-darker;
- border-color: $gray;
+ border-bottom: 1px solid gray('400');
+ border-color: gray('700');
box-shadow: none;
font-weight: 500;
}
.searchIcon {
@include o-position-absolute(4px, 0);
- color: $gray;
+ color: gray('700');
}
}
}
@@ -60,7 +60,7 @@
border: 0;
.btn-primary, .btn-link {
- padding: $padding-small-vertical $padding-small-horizontal;
+ padding: $btn-padding-y-sm $btn-padding-x-sm;
}
.btn-link {
@@ -70,34 +70,34 @@
}
.o_setting_container {
- @include o-flex-display;
- @include o-flex(1, 1, auto);
+ display: flex;
+ flex: 1 1 auto;
overflow: auto;
- @media (max-width: $screen-xs-max) {
- @include o-flex-flow(column, nowrap);
+ @include media-breakpoint-down(sm) {
+ flex-flow: column nowrap;
}
.settings_tab {
- @include o-flex-display;
- @include o-flex(0, 0, auto);
- @include o-flex-flow(column, nowrap);
- background: $gray-dark;
+ display: flex;
+ flex: 0 0 auto;
+ flex-flow: column nowrap;
+ background: gray('900');
overflow: auto;
padding-top: $o-horizontal-padding*0.5;
- @media (max-width: $screen-xs-max) {
- @include o-flex(0, 0, $o-base-settings-mobile-tabs-height);
- @include o-inline-flex-display;
+ @include media-breakpoint-down(sm) {
+ flex: 0 0 $o-base-settings-mobile-tabs-height;
+ display: inline-flex;
position: relative;
overflow: hidden;
padding: 0;
}
.selected {
- background-color: $gray-darker;
- box-shadow: inset 3px 0 0 $o-brand-optional;
+ background-color: gray('900');
+ box-shadow: inset 3px 0 0 $o-brand-primary;
.app_name {
color: white;
@@ -105,10 +105,10 @@
}
.tab {
- @include o-flex-display;
+ display: flex;
padding: 0 $o-horizontal-padding*2 0 $o-horizontal-padding;
height: 40px;
- color: $gray-lighter-darker;
+ color: gray('400');
font-size: 13px;
line-height: 40px;
cursor: pointer;
@@ -119,7 +119,7 @@
}
// Mobile Tabs
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
display: block;
@include o-position-absolute($left:100%);
@include size(auto, $o-base-settings-mobile-tabs-height);
@@ -128,8 +128,8 @@
font-size: 14px;
font-weight: 500;
line-height: inherit;
- @include o-transition(0.2s, all);
- @include o-transform(translate3d(0,0,0));
+ transition: 0.2s all ease 0s;
+ transform: translate3d(0,0,0);
.app_name {
display: block;
@@ -138,11 +138,11 @@
&:after {
content: '';
- background: $o-brand-optional;
+ background: $o-brand-primary;
opacity: 0;
@include o-position-absolute(auto, 0, 0, 0);
@include size(100%, 3px);
- @include o-transition(0.2s, all);
+ transition: 0.2s all ease 0s;
}
&.previous, &.before {
@@ -171,7 +171,7 @@
.settings {
position: relative;
- @include o-flex(1, 1, 100%);
+ flex: 1 1 100%;
background-color: $o-view-background-color;
overflow: auto;
@@ -179,7 +179,7 @@
h2 {
margin-bottom: 0;
@include o-base-settings-horizontal-padding;
- background-color: $gray-lighter;
+ background-color: gray('200');
font-size: 15px;
font-weight: bold;
@@ -190,19 +190,20 @@
}
.o_settings_container {
- max-width: $screen-md-min; // Provide a maximum container size to ensure readability
+ max-width: map-get($grid-breakpoints, lg); // Provide a maximum container size to ensure readability
@include o-base-settings-horizontal-padding(0);
}
}
.settingSearchHeader {
- @include o-flex-display;
+ display: flex;
margin: 30px 0 10px;
@include o-base-settings-horizontal-padding;
- background-color: $gray-lighter;
+ background-color: gray('200');
.icon {
- @include square(25px);
+ width: 25px;
+ height: 25px;
margin-right: 10px;
}
diff --git a/addons/web/static/src/scss/bootstrap_overridden.scss b/addons/web/static/src/scss/bootstrap_overridden.scss
index 9701ead0539..8d0cf644b62 100644
--- a/addons/web/static/src/scss/bootstrap_overridden.scss
+++ b/addons/web/static/src/scss/bootstrap_overridden.scss
@@ -1,85 +1,91 @@
-// ------------------------------------------------------------------
-// Bootstrap variables
-// ------------------------------------------------------------------
-
-//== Grid
-$grid-gutter-width: $o-horizontal-padding*2;
-
-//== Colors
-$brand-primary: $o-brand-primary;
-
-//== Greyscale
-$gray-base: #000;
-$gray-darker: lighten($gray-base, 13.5%);
-$gray-dark: lighten($gray-base, 20%);
-$gray: lighten($gray-base, 33.5%);
-$gray-light: $o-color-gray-light;
-$gray-lighter: $o-color-silver;
-
-//== Titles
-$font-size-h1: $o-font-size-base + 13px;
-$font-size-h2: $o-font-size-base + 7px;
-$font-size-h3: $o-font-size-base + 3px;
-$font-size-h4: $o-font-size-base + 2px;
-$font-size-h5: $o-font-size-base + 1px;
-$font-size-h6: $o-font-size-base;
-
-//== Scaffolding
+///
+/// This file is a copy of the bootstrap _variables.scss file where all the
+/// left-untouched variables definition have been removed.
+///
+
+//
+// Color system
+//
+
+// All of those are BS default
+$white: #fff !default;
+$gray-100: $o-gray-100 !default;
+$gray-200: #e9ecef !default;
+$gray-300: #dee2e6 !default;
+$gray-400: #ced4da !default;
+$gray-500: #adb5bd !default;
+$gray-600: #6c757d !default;
+$gray-700: #495057 !default;
+$gray-800: #343a40 !default;
+$gray-900: #212529 !default;
+$black: #000 !default;
+
+$primary: $o-brand-primary;
+$secondary: $white;
+
+// Body
+//
+// Settings for the `<body>` element.
+
$body-bg: $o-brand-secondary;
-$text-color: $o-main-text-color;
-$link-color: $o-brand-optional;
+$body-color: $o-main-text-color;
+
+// Links
+//
+// Style anchor elements.
+
$link-hover-decoration: none;
-//== Typography
+// Grid columns
+//
+// Set the number of columns and specify the width of the gutters.
+
+$grid-gutter-width: $o-horizontal-padding * 2;
+
+// Components
+//
+// Define common padding and border radius sizes and more.
+
+$border-radius: 3px;
+
+$component-active-color: $o-brand-primary;
+$component-active-bg: $gray-200;
+
+// Fonts
+//
+// Font, line-height, and color for body text, headings, and more.
+
$font-family-sans-serif: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif;
+
$font-size-base: $o-font-size-base;
-$headings-font-weight: bold;
$line-height-base: $o-line-height-base;
-//== Components
-$border-radius-base: 3px;
-$component-active-bg: $gray-lighter;
-$component-active-color: $o-brand-optional;
+$h1-font-size: $o-font-size-base * 2.0;
+$h2-font-size: $o-font-size-base * 1.5;
+$h3-font-size: $o-font-size-base * 1.3;
+$h4-font-size: $o-font-size-base * 1.2;
+$h5-font-size: $o-font-size-base * 1.1;
-//== Badges
-$badge-bg: $o-brand-optional;
-$badge-color: white;
-$badge-line-height: $o-line-height-base;
-$badge-font-weight: normal;
+$headings-font-weight: bold;
+
+// Tables
+//
+// Customizes the `.table` component with basic values, each used across all table variations.
+
+$table-accent-bg: #EFEFF8; // FIXME: expose
+$table-hover-bg: darken($table-accent-bg, 5%);
+
+// Dropdowns
+//
+// Dropdown menu container and contents.
+
+$dropdown-border-color: $gray-300;
-//== Breadcrumbs
-$breadcrumb-active-color: #777777;
-$breadcrumb-bg: $o-control-panel-background-color;
-$breadcrumb-color: #777777;
-$breadcrumb-padding-horizontal: 0;
-$breadcrumb-padding-vertical: 0;
-
-//== Buttons
-$btn-default-bg: white;
-$btn-default-border: #cccccc;
-$btn-default-color: $o-main-text-color;
-$btn-primary-bg: $o-brand-optional;
-$btn-primary-border: $o-brand-optional;
-$btn-primary-color: white;
-
-//== Dropdowns
-$dropdown-bg: white;
-$dropdown-border: $gray-lighter-dark;
-$dropdown-divider-bg: $gray-lighter-dark;
$dropdown-link-color: $o-main-text-color;
-$dropdown-link-hover-color: $gray-dark;
-$dropdown-link-hover-bg: $gray-lighter;
-$dropdown-link-active-color: $component-active-color;
-$dropdown-link-active-bg: $component-active-bg;
-$dropdown-link-disabled-color: $gray-light;
-$dropdown-header-color: $gray-light;
-
-//== Modals
-$modal-sm: 300px;
-$modal-md: 650px;
-$modal-lg: 980px;
-$modal-inner-padding: $o-horizontal-padding;
-$modal-title-padding: $o-horizontal-padding;
+$dropdown-link-hover-color: $gray-900;
+$dropdown-link-hover-bg: $gray-200;
+
+// Z-index master list
// Change the z-index of the modal-backdrop elements to be equal to the
// modal elements' ones. Bootstrap does not support multi-modals, and without
@@ -90,31 +96,45 @@ $modal-title-padding: $o-horizontal-padding;
// cannot happen in odoo though as modals are not hidden but removed from
// the DOM and are always put at the end of the body when opened.
//
-// Note that the variable $zindex-modal-background may be renamed/removed in
-// newer versions of bootstrap.
-//
// TODO the following code was disabled because it is saas-incompatible
//
-// $zindex-modal-background: $zindex-modal;
+// $zindex-modal-backdrop: $zindex-modal;
+
+// Navs
+
+$nav-tabs-link-active-bg: $white;
-//== Navs
-$nav-link-padding: 10px 15px;
$nav-pills-border-radius: 0;
-$nav-pills-active-link-hover-color: white;
-$nav-pills-active-link-hover-bg: $o-brand-optional;
-$nav-tabs-active-link-hover-bg: white;
-
-//== Navbar
-$navbar-height: $o-navbar-height - 2;
-$navbar-margin-bottom: 0;
-$navbar-inverse-bg: #222222;
-$navbar-inverse-link-color: #9d9d9d;
-$navbar-inverse-link-hover-bg: #222222;
-$navbar-inverse-toggle-hover-bg: #222222;
-$navbar-border-radius: 0;
-
-//== Tables
-$table-bg-accent: #efeff8; // FIXME: expose
-$table-bg-hover: darken($table-bg-accent,5%);
-
-$icon-font-path: "/web/static/lib/bootstrap/fonts/";
+$nav-pills-link-active-color: $white;
+$nav-pills-link-active-bg: $o-brand-primary;
+
+// Navbar
+
+// FIXME $navbar-height ? $navbar-margin-bottom ? $navbar-inverse-* ? $navbar-border-radius ?
+
+// Badges
+
+// FIXME $badge-bg, $badge-color, $badge-line-height ?
+$badge-font-weight: normal;
+
+// Modals
+
+// Padding applied to the modal body
+$modal-inner-padding: $o-horizontal-padding;
+
+// FIXME $modal-title-padding ?
+
+$modal-lg: 980px;
+$modal-md: 650px;
+
+// Breadcrumbs
+
+$breadcrumb-padding-y: 0;
+$breadcrumb-padding-x: 0;
+$breadcrumb-margin-bottom: 0;
+
+$breadcrumb-bg: $o-control-panel-background-color;
+// FIXME $breadcrumb-color ?
+$breadcrumb-active-color: #777777;
+
+// FIXME $icon-font-path ?
diff --git a/addons/web/static/src/scss/bootstrap_overridden_frontend.scss b/addons/web/static/src/scss/bootstrap_overridden_frontend.scss
index e69de29bb2d..19ced6c9d8f 100644
--- a/addons/web/static/src/scss/bootstrap_overridden_frontend.scss
+++ b/addons/web/static/src/scss/bootstrap_overridden_frontend.scss
@@ -0,0 +1,3 @@
+
+$black: black;
+$white: white;
diff --git a/addons/web/static/src/scss/bs_mixins_overrides.scss b/addons/web/static/src/scss/bs_mixins_overrides.scss
new file mode 100644
index 00000000000..fd08c94a217
--- /dev/null
+++ b/addons/web/static/src/scss/bs_mixins_overrides.scss
@@ -0,0 +1,38 @@
+//------------------------------------------------------------------------------
+// Bootstrap Mixins and Functions Extensions
+// Those will affect the way bootstrap is generated wherever bootstrap is used
+//------------------------------------------------------------------------------
+
+// Override background utilities so that they come with a default contrasted
+// color (especially useful in the frontend editor for example). Also modifies
+// the way .text-muted elements are rendered in those environments.
+@mixin bg-variant($parent, $color, $text-color: null) {
+ #{$parent} {
+ $-yiq-color: if($text-color, $text-color, color-yiq($color));
+ background-color: $color !important;
+ color: $-yiq-color; // not important so that text utilities still work
+
+ .text-muted {
+ color: rgba($-yiq-color, 0.4) !important;
+ }
+ }
+ a#{$parent},
+ button#{$parent} {
+ $-darken-color: darken($color, 10%);
+ @include hover-focus {
+ background-color: $-darken-color !important;
+ color: if($text-color, $text-color, color-yiq($-darken-color));
+ }
+ }
+}
+@mixin bg-gradient-variant($parent, $color, $text-color: null) {
+ #{$parent} {
+ $-yiq-color: if($text-color, $text-color, color-yiq($color));
+ background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x !important;
+ color: $-yiq-color;
+
+ .text-muted {
+ color: rgba($-yiq-color, 0.4) !important;
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/control_panel.scss b/addons/web/static/src/scss/control_panel.scss
index 13913bdf3d5..b4f7d189f9e 100644
--- a/addons/web/static/src/scss/control_panel.scss
+++ b/addons/web/static/src/scss/control_panel.scss
@@ -1,14 +1,13 @@
.o_control_panel {
- @include o-flex-display;
- @include o-flex-flow(row, wrap);
+ display: flex;
+ flex-flow: row wrap;
border-bottom: 1px solid darken($o-control-panel-background-color, 20%);
@include o-webclient-padding($top: 10px, $bottom: 10px);
background-color: $o-control-panel-background-color;
> .breadcrumb {
width: 50%;
- margin: 0px;
font-size: 18px;
> li {
@@ -36,8 +35,8 @@
}
> .o_cp_left {
- @include o-flex-display;
- @include o-justify-content(space-between);
+ display: flex;
+ justify-content: space-between;
width: 50%;
margin-top: 5px;
@@ -55,10 +54,10 @@
}
.o_form_binary_form span {
padding: 3px 25px;
- color: $btn-default-color;
+ color: $o-brand-primary;
}
.o_form_binary_form:hover {
- background-color: $table-bg-hover;
+ background-color: $table-hover-bg;
}
}
.o_sidebar_delete_attachment {
@@ -71,7 +70,7 @@
}
> .o_cp_right {
- @include o-flex-display;
+ display: flex;
width: 50%;
margin-top: 5px;
@@ -79,11 +78,11 @@
margin: auto 0 auto auto;
padding-left: 5px;
text-align: center;
- @include user-select(none);
+ user-select: none;
> div {
- @include o-flex-display;
- @include o-align-items(center);
+ display: flex;
+ align-items: center;
}
.o_pager_counter {
@@ -93,7 +92,7 @@
> .o_cp_switch_buttons > .btn:first-child {
margin-left: $o-horizontal-padding;
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
margin-left: $o-horizontal-padding - 6;
}
}
@@ -101,11 +100,11 @@
}
.o_x2m_control_panel {
- @include o-flex-display;
- @include o-flex-flow(row, wrap);
+ display: flex;
+ flex-flow: row wrap;
.o_cp_buttons {
- @include o-flex-display;
+ display: flex;
margin-right: auto;
> div {
margin-top: 5px;
@@ -115,7 +114,7 @@
}
}
.o_cp_pager {
- @include o-flex-display;
+ display: flex;
margin-left: auto;
}
}
diff --git a/addons/web/static/src/scss/data_export.scss b/addons/web/static/src/scss/data_export.scss
index 17cec27d3a5..c03d13b355b 100644
--- a/addons/web/static/src/scss/data_export.scss
+++ b/addons/web/static/src/scss/data_export.scss
@@ -1,23 +1,23 @@
.o_web_client .o_export {
- @include o-flex(1, 1, auto);
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
+ flex: 1 1 auto;
+ display: flex;
+ flex-flow: column nowrap;
min-height: 0;
> p, > .row {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
.o_export_panel {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
position: relative;
min-height: 0;
> div {
height: 100%;
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
- @include o-justify-content(center);
+ display: flex;
+ flex-flow: column nowrap;
+ justify-content: center;
&.o_left_panel { // Needed because of chrome
@include o-position-absolute($top: 0, $bottom: 0, $left: 0, $right: 57%);
@@ -30,18 +30,18 @@
}
> h4, > div {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
> button {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
margin-top: 10px;
}
.o_left_field_panel, .o_fields_list {
border: 1px solid $o-brand-lightsecondary;
overflow: auto;
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
min-height: 0;
}
@@ -49,10 +49,10 @@
cursor: pointer;
position: relative;
padding-left: 20px;
- @include user-select(none);
+ user-select: none;
&.o_selected > .o_tree_column {
- background-color: $o-brand-primary;
+ background-color: $o-brand-odoo;
color: white;
}
@@ -74,16 +74,16 @@
}
.o_save_list, .o_exported_lists {
- @include o-flex-display;
- @include o-align-items(baseline);
+ display: flex;
+ align-items: baseline;
> label, > button {
margin: 0 0 5px;
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
> input, > select {
width: 0;
- @include o-flex(1, 0, auto);
+ flex: 1 0 auto;
}
}
}
diff --git a/addons/web/static/src/scss/datepicker.scss b/addons/web/static/src/scss/datepicker.scss
index d8d4ba1d520..c4df0ca2ed2 100644
--- a/addons/web/static/src/scss/datepicker.scss
+++ b/addons/web/static/src/scss/datepicker.scss
@@ -27,24 +27,29 @@
}
}
-// Need to put datetimepicker widget above everything else
-// The '.dropdown-menu' part is needed to override default bootstrap rule as
+
+// The 'div.dropdown-menu' part is needed to override default bootstrap rule as
// this file is unfortunately placed in common assets.
-.bootstrap-datetimepicker-widget.dropdown-menu {
+div.dropdown-menu.bootstrap-datetimepicker-widget{
+ // Need to put datetimepicker widget above everything else
z-index: $zindex-modal + 1;
+
+ // Also fix the dropdown width
+ width: auto;
+ min-width: 15rem;
}
.datepicker {
- .table-condensed {
+ .table-sm {
> thead {
color: white;
- background-color: $o-brand-primary;
+ background-color: $o-brand-odoo;
> tr {
&:first-child {
th:hover {
color: white;
- background-color: darken($o-brand-primary, 10%);
+ background-color: darken($o-brand-odoo, 10%);
}
}
@@ -62,12 +67,12 @@
> tr {
> td {
&.active, .active {
- background-color: $o-brand-optional;
+ background-color: $o-brand-primary;
border-radius: 100px;
}
&.today:before {
- border-bottom-color: $o-brand-optional;
+ border-bottom-color: $o-brand-primary;
}
}
}
diff --git a/addons/web/static/src/scss/domain_selector.scss b/addons/web/static/src/scss/domain_selector.scss
index 6755bed49e9..b35934973b9 100644
--- a/addons/web/static/src/scss/domain_selector.scss
+++ b/addons/web/static/src/scss/domain_selector.scss
@@ -9,12 +9,12 @@
// Rows in a domain node (selector) have a minimum height and holds the control panel
.o_domain_selector_row {
- @include o-flex-display;
- @include o-align-items(center);
+ display: flex;
+ align-items: center;
min-height: $o-domain-selector-row-height;
> * {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
> .o_domain_node_control_panel {
@@ -35,7 +35,7 @@
padding-left: 5px;
&:hover {
- color: $brand-danger;
+ color: theme-color('danger');
}
}
}
@@ -74,7 +74,7 @@
display: block;
margin-top: 16px;
padding: 8px 10px 12px;
- background: $gray-dark;
+ background: gray('900');
color: rgba(white, 0.5);
font-family: monospace;
font-weight: normal;
@@ -92,7 +92,7 @@
// Rules specific to domain parts which do not contain sub-domain parts
&.o_domain_leaf {
&.o_read_mode {
- @include o-inline-flex-display;
+ display: inline-flex;
margin-right: 4px;
}
@@ -119,21 +119,21 @@
}
> .o_domain_leaf_edition {
- @include o-flex-display;
+ display: flex;
width: 100%;
padding: 4px ($o-domain-selector-panel-space/2) 4px 0;
> * {
- @include o-flex(1, 1, 15%); // operator select
+ flex: 1 1 15%; // operator select
width: auto;
background-color: white;
&:first-child { // field selector
- @include o-flex(0, 1, 55%);
+ flex: 0 1 55%;
}
&:last-child { // field value
- @include o-flex(1, 1, 25%);
+ flex: 1 1 25%;
}
+ * {
@@ -146,13 +146,13 @@
}
.o_domain_leaf_value_tags {
- @include o-flex-display;
+ display: flex;
> * {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
> input {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
width: 0;
min-width: 50px;
}
@@ -164,7 +164,7 @@
}
// Animation effects
- @include o-transition(margin-bottom, .05s, ease, .05s);
+ transition: margin-bottom .05s ease .05s;
&::after {
content: "";
@@ -172,8 +172,8 @@
display: block;
height: $o-domain-animation-bar-height;
max-height: 0;
- @include o-linear-gradient(45deg, rgba($o-brand-optional, 0.4), rgba($o-brand-optional, 0.1));
- @include o-transition(max-height, .05s, ease, .05s);
+ background-image: linear-gradient(45deg, rgba($o-brand-primary, 0.4), rgba($o-brand-primary, 0.1));
+ transition: max-height .05s ease .05s;
}
&.o_hover_btns, &.o_hover_add_node {
@@ -191,11 +191,11 @@
&.o_hover_add_node {
margin-bottom: $o-domain-animation-bar-height;
- @include o-transition(margin, .15s, ease, .5s);
+ transition: margin .15s ease .5s;
&::after {
max-height: $o-domain-animation-bar-height;
- @include o-transition(max-height, .15s, ease, .5s);
+ transition: max-height .15s ease .5s;
}
&.o_hover_add_inset_node::after {
left: $o-domain-selector-indent;
diff --git a/addons/web/static/src/scss/dropdown.scss b/addons/web/static/src/scss/dropdown.scss
index 7db8b2fcb3c..90deb20083f 100644
--- a/addons/web/static/src/scss/dropdown.scss
+++ b/addons/web/static/src/scss/dropdown.scss
@@ -5,7 +5,7 @@
.ui-autocomplete { // Copy style of bootstrap dropdown
background-image: none;
background-color: $dropdown-bg;
- border: 1px solid $dropdown-border;
+ border: $dropdown-border-width solid $dropdown-border-color;
font-size: $font-size-base;
padding: 5px 0px;
box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176);
@@ -21,7 +21,7 @@
&.ui-state-focus {
background-image: none;
- background-color: $o-brand-primary;
+ background-color: $o-brand-odoo;
border: none;
font-weight: normal;
margin: 0;
@@ -29,7 +29,7 @@
&.o_m2o_dropdown_option {
padding-left: 20px;
> a {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
}
}
}
@@ -41,7 +41,7 @@
.o_inline_dropdown {
position: relative;
- &> .dropdown-menu {
+ & > .dropdown-menu {
top: 0;
left: 100%;
}
@@ -52,9 +52,12 @@
}
@mixin dropdown-menu-mixin {
- .open .dropdown-menu > li {
- position: relative; // to allow absolute positionning inside the li
- > a {
+ .show .dropdown-menu {
+ > * {
+ position: relative; // to allow absolute positionning inside the items
+ }
+
+ .dropdown-item {
&:focus, &:active, &:focus:active {
outline: none;
}
@@ -62,11 +65,11 @@
@extend %dropdown-li-a-padding;
}
- &.dropdown-header {
+ .dropdown-header {
@extend %dropdown-li-a-padding;
color: $o-main-text-color;
- @media (max-width: $screen-sm-max) {
+ @include media-breakpoint-down(md) {
color: white;
text-decoration: underline;
}
diff --git a/addons/web/static/src/scss/dropdown_extra.scss b/addons/web/static/src/scss/dropdown_extra.scss
index c14144e02d3..ca57d9561f2 100644
--- a/addons/web/static/src/scss/dropdown_extra.scss
+++ b/addons/web/static/src/scss/dropdown_extra.scss
@@ -1,9 +1,9 @@
.ui-autocomplete .ui-menu-item {
&.ui-state-focus {
- background-color: $o-brand-primary;
+ background-color: $o-brand-odoo;
}
&.o_m2o_dropdown_option > a {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
}
&.ui-state-focus > a,
&.ui-state-focus.o_m2o_dropdown_option > a {
@@ -41,7 +41,7 @@
margin: 0;
padding: 2px 8px;
&:hover {
- @include o-vertical-gradient(#f0f0fa, #eeeef6);
+ background-image: linear-gradient(to bottom, #f0f0fa, #eeeef6);
box-shadow: none;
}
> a {
diff --git a/addons/web/static/src/scss/dropdown_menu.scss b/addons/web/static/src/scss/dropdown_menu.scss
index 8024783d3c2..8f5b0c1f00a 100644
--- a/addons/web/static/src/scss/dropdown_menu.scss
+++ b/addons/web/static/src/scss/dropdown_menu.scss
@@ -1,38 +1,23 @@
.o_dropdown_menu {
- > li.divider:first-child {
+ > .dropdown-divider:first-child {
display: none;
}
- max-height: calc(100vh - 125px);
+ max-height: calc(100vh - 125px); // FIXME
overflow: auto;
- .o_submenu_switcher {
- float:right;
- width: 25px;
- text-align: center;
- }
- .o_trash_button {
- float:right;
- + .o_submenu_switcher {
- margin-right: 6px;
- }
- }
- ul {
- list-style-type: none;
- padding-left: 20px;
- }
- li.o_menu_item {
+ .o_menu_item {
position: relative;
- > a {
+ > .dropdown-item {
color: $o-main-text-color;
- padding-right: 25px;
+
&:hover {
color: darken($o-main-text-color, 10%);
}
}
&.selected {
- > a {
+ > .dropdown-item {
color: darken($o-main-text-color, 10%);
font-weight: bold;
&:before {
@@ -43,7 +28,7 @@
}
}
}
- li.divider:first-child {
+ .dropdown-divider:first-child {
display: none;
}
.o_item_option {
diff --git a/addons/web/static/src/scss/fields.scss b/addons/web/static/src/scss/fields.scss
index 370fdc036b3..cbf0eec7d01 100644
--- a/addons/web/static/src/scss/fields.scss
+++ b/addons/web/static/src/scss/fields.scss
@@ -6,8 +6,8 @@
// 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
+ color: theme-color('danger')!important;
+ border-color: theme-color('danger')!important; // enterprise o_required_modifier rule overrides this without !important
}
}
@@ -39,15 +39,15 @@
// Flex fields (inline)
&.o_field_many2one, &.o_field_radio, &.o_field_many2manytags, &.o_field_percent_pie, &.o_field_monetary, &.o_field_binary_file {
- @include o-inline-flex-display;
+ display: inline-flex;
> span, > button {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
}
// Dropdowns input (many2one, ...)
.o_input_dropdown {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
position: relative;
width: 100%;
@@ -75,28 +75,28 @@
// Monetary
&.o_field_monetary {
&.o_input {
- @include o-align-items(baseline);
+ align-items: baseline;
> input {
width: 100px;
- @include o-flex(1, 0, auto);
+ flex: 1 0 auto;
}
}
}
// Many2many tags
&.o_field_many2manytags {
- @include o-flex-flow(row, wrap);
- @include o-align-items(baseline);
+ flex-flow: row wrap;
+ align-items: baseline;
> .o_field_widget {
- @include o-flex(1, 0, 100px);
+ flex: 1 0 100px;
position: initial;
max-width: 100%;
}
> .badge {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
border: 0;
font-size: 12px;
color: white;
@@ -119,7 +119,7 @@
display: inline-block;
margin: 5px 5px 0 0; // FIXME was $o-kanban-inner-hmargin before scss convertion
border: 1px solid white;
- box-shadow: 0 0 0 1px $gray-lighter-dark;
+ box-shadow: 0 0 0 1px gray('300');
> a {
display: block;
@@ -225,7 +225,7 @@
// Specific success color for toggle_button widget
.fa.o_toggle_button_success {
- color: $brand-success;
+ color: theme-color('success');
}
// Handle widget
@@ -239,21 +239,21 @@
margin: 0px 0px 4px 4px;
padding: 1px 6px;
color: $o-main-color-muted;
- border: 1px solid $o-color-silver-dark;
+ border: 1px solid gray('300');
cursor: pointer;
&.active {
- color: $o-brand-optional;
- border-color: $o-brand-optional;
+ color: $o-brand-primary;
+ border-color: $o-brand-primary;
}
&:hover:not(.active) {
- color: darken($o-color-silver-dark, 30%);
- border-color: darken($o-color-silver-dark, 30%);
+ color: darken(gray('300'), 30%);
+ border-color: darken(gray('300'), 30%);
}
}
}
// Radio buttons
&.o_field_radio {
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
display: inline-block;
}
.o_radio_input {
@@ -261,17 +261,7 @@
}
.o_radio_item {
- @include o-flex(0, 0, auto);
- @include o-flex-display;
- @include o-align-items(center);
-
- > input {
- @include o-flex(0, 0, auto);
- margin: 0 $o-form-spacing-unit 0 0;
- }
- > label {
- margin: 0;
- }
+ flex: 0 0 auto;
}
&.o_horizontal {
@@ -281,7 +271,7 @@
}
&.o_vertical {
- @include o-flex-flow(column, nowrap);
+ flex-flow: column nowrap;
.o_radio_item {
margin-bottom: $o-form-spacing-unit;
}
@@ -290,7 +280,7 @@
// Percent pie
&.o_field_percent_pie {
- @include o-align-items(center);
+ align-items: center;
> .o_pie {
position: relative;
@@ -299,7 +289,7 @@
margin-right: 10px;
border-radius: 100%;
overflow: hidden;
- background-color: $o-brand-optional;
+ background-color: $o-brand-primary;
&:after { // Outside pie border to go over border-radius irregularities
content: " ";
@@ -311,7 +301,7 @@
.o_mask {
@include o-position-absolute(0, 0);
- @include o-transform-origin(0);
+ transform-origin: 0;
width: 50%;
height: 100%;
background-color: $o-view-background-color;
@@ -321,14 +311,14 @@
}
.o_pie_value {
- @include o-flex-display;
- @include o-justify-content(center);
- @include o-align-items(center);
+ display: flex;
+ justify-content: center;
+ align-items: center;
border-radius: 100%;
font-weight: 700;
- color: $o-brand-primary;
+ color: $o-brand-odoo;
}
}
}
@@ -351,7 +341,7 @@
width: 100%;
color: white;
- background-color: $o-brand-optional;
+ background-color: $o-brand-primary;
opacity: 0;
transition: opacity ease 400ms;
@@ -365,7 +355,7 @@
cursor: pointer;
}
}
- @media (max-width: $screen-xs-min) {
+ @include media-breakpoint-down(xs, $o-extra-grid-breakpoints) {
.o_form_image_controls{
position: initial;
opacity: 1;
@@ -375,10 +365,10 @@
margin: 0px;
text-align: center;
&.o_select_file_button{
- background: $o-brand-optional;
+ background: $o-brand-primary;
}
&.o_clear_file_button{
- background: $brand-danger;
+ background: theme-color('danger');
}
}
}
@@ -389,7 +379,7 @@
}
&.o_field_invalid > img {
- border: 1px solid $brand-danger;
+ border: 1px solid theme-color('danger');
}
}
@@ -417,9 +407,9 @@
&.o_field_copy {
position: relative;
border-radius: 5px;
- border: 1px solid $btn-primary-border;
- font-size: $font-size-small;
- color: $o-brand-optional;
+ border: 1px solid $primary;
+ font-size: $font-size-sm;
+ color: $o-brand-primary;
font-weight: $badge-font-weight;
text-align: center;
.o_clipboard_button {
diff --git a/addons/web/static/src/scss/fields_extra.scss b/addons/web/static/src/scss/fields_extra.scss
index 7e45291305f..47fca992eb5 100644
--- a/addons/web/static/src/scss/fields_extra.scss
+++ b/addons/web/static/src/scss/fields_extra.scss
@@ -43,7 +43,7 @@
margin-left: 5px;
&:after { // Outside pie border to go over border-radius irregularities
- border: 1px solid $o-brand-primary;
+ border: 1px solid $o-brand-odoo;
}
.o_pie_value {
diff --git a/addons/web/static/src/scss/form_view.scss b/addons/web/static/src/scss/form_view.scss
index f46de22e9db..730f5b9521b 100644
--- a/addons/web/static/src/scss/form_view.scss
+++ b/addons/web/static/src/scss/form_view.scss
@@ -16,7 +16,7 @@
}
.oe_inline {
width: auto!important;
- @media (min-width: $screen-xs-min) {
+ @include media-breakpoint-up(vsm, $o-extra-grid-breakpoints) {
&.o_inner_group {
width: 1px!important;
}
@@ -31,19 +31,19 @@
float: right!important;
}
- @media (min-width: $screen-xs-min) {
+ @include media-breakpoint-up(vsm, $o-extra-grid-breakpoints) {
.o_row {
&, &.o_field_widget { // Some field may want to use o_row as root and these rules must prevalue
- @include o-flex-display;
+ display: flex;
width: auto!important;
}
- @include o-align-items(baseline);
+ align-items: baseline;
min-width: 50px;
margin: 0 (-$o-form-spacing-unit/2);
> div, > span, > button, > label, > a, > input { // > * did not add a level of priority to the rule
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
width: auto!important;
margin-right: $o-form-spacing-unit/2;
margin-left: $o-form-spacing-unit/2;
@@ -57,7 +57,7 @@
padding-bottom: 0;
}
> .o_field_boolean {
- @include o-align-self(center);
+ align-self: center;
}
}
}
@@ -100,17 +100,17 @@
}
.oe_title {
- max-width: $container-sm - (2 * $o-horizontal-padding);
+ max-width: map-get($container-max-widths, md) - (2 * $o-horizontal-padding);
}
- @media (min-width: $screen-xs-min) {
+ @include media-breakpoint-up(vsm, $o-extra-grid-breakpoints) {
.o_row {
> .o_field_widget, > div {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
width: 0!important; // 3rd flex argument does not work with input (must be auto and real width 0)
&.o_field_boolean, &.o_priority {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
width: auto!important;
}
}
@@ -140,25 +140,25 @@
// Statusbar
.o_form_statusbar {
position: relative; // Needed for the "More" dropdown
- @include o-flex-display;
- @include o-justify-content(space-between);
+ display: flex;
+ justify-content: space-between;
padding-left: $o-horizontal-padding;
- border-bottom: 1px solid $gray-lighter-darker;
+ border-bottom: 1px solid gray('400');
background-color: $o-view-background-color;
> .o_statusbar_buttons, > .o_statusbar_status {
- @include o-flex-display;
- @include o-align-items(center);
- @include o-align-content(space-around);
+ display: flex;
+ align-items: center;
+ align-content: space-around;
}
> .o_field_widget {
- @include o-align-self(center);
+ align-self: center;
margin-bottom: 0px;
}
> .o_statusbar_buttons {
- @include o-flex-flow(row, wrap);
+ flex-flow: row wrap;
> .btn {
$o-statusbar-buttons-vmargin: 4px;
@@ -171,9 +171,9 @@
> .o_statusbar_status {
margin-left: auto;
- @include o-flex-flow(row-reverse, wrap-reverse);
- @include o-align-self(stretch);
- @include o-align-items(stretch);
+ flex-flow: row-reverse wrap-reverse;
+ align-self: stretch;
+ align-items: stretch;
overflow-x: hidden; // to prevent horizontal scroll due to last arrow
> .o_arrow_button {
@@ -182,17 +182,17 @@
font-weight: bold;
position: relative;
padding-left: $o-statusbar-arrow-width*2;
- color: $gray;
+ color: gray('700');
border-width: 0 0 0;
border-radius: 0;
- @include o-transition(all, 0.1s);
+ transition: all 0.1s ease 0s;
&:first-child {
padding-right: $o-horizontal-padding; // Compensate container padding
}
&:last-child {
padding-left: $o-horizontal-padding - 1;
- border-left: 1px solid $gray-lighter-darker;
+ border-left: 1px solid gray('400');
}
&:active {
@@ -203,7 +203,7 @@
opacity: 1.0;
color: $text-muted;
pointer-events: none;
- border-left: 1px solid $gray-lighter-dark;
+ border-left: 1px solid gray('300');
}
&:before, &:after {
@@ -215,34 +215,34 @@
border-bottom: ceil($o-statusbar-height/2) solid transparent;
border-right: none;
border-left: $o-statusbar-arrow-width solid $o-view-background-color;
- @include o-transition(border, 0.2s);
+ transition: border 0.2s ease 0s;
-moz-transform: scale(0.9999); // Smooth the triangle on firefox
}
&:not(.disabled) {
&:hover, &:active, &:focus {
- color: $o-brand-optional;
- background-color: $gray-lighter;
+ color: $o-brand-primary;
+ background-color: gray('200');
&:after {
- border-left-color: $gray-lighter;
+ border-left-color: gray('200');
}
}
}
&:before {
right: -$o-statusbar-arrow-width;
- border-left-color: $gray-lighter-dark;
+ border-left-color: gray('300');
}
&.btn-primary.disabled {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
font-size: 11px;
- background-color: $gray-lighter;
+ background-color: gray('200');
cursor: default;
&:after {
- border-left-color: $gray-lighter;
+ border-left-color: gray('200');
}
}
@@ -274,7 +274,7 @@
padding: 5px 0 2px 0;
min-width: 100px;
- > li > .btn {
+ .dropdown-item.btn {
min-width: 100%;
margin-bottom: 3px;
}
@@ -349,7 +349,7 @@
width: 100%;
> .btn {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
padding: 0 10px;
}
}
@@ -361,7 +361,7 @@
// Makes extra buttons (e.g. m2o external button) overflow on the
// right padding of the parent element
.o_input_dropdown {
- @include o-flex(1, 0, auto);
+ flex: 1 0 auto;
}
}
@@ -377,7 +377,7 @@
// Separators
.o_horizontal_separator {
- font-size: $font-size-h2;
+ font-size: $h2-font-size;
margin: $o-form-spacing-unit 0;
&:empty {
height: $o-form-spacing-unit * 2;
@@ -425,7 +425,7 @@
// Text field with oe_inline class
.o_field_text.oe_inline {
width: 100%!important;
- @media (min-width: $screen-xs-min) {
+ @include media-breakpoint-up(vsm, $o-extra-grid-breakpoints) {
width: 45%!important;
}
}
@@ -463,7 +463,7 @@
.o_field_widget {
text-align: right;
- @include o-justify-content(flex-end);
+ justify-content: flex-end;
width: 100%;
}
}
@@ -475,7 +475,7 @@
.oe_subtotal_footer_separator {
width: 100%;
text-align: right;
- border-top: 1px solid $gray-lighter-dark;
+ border-top: 1px solid gray('300');
font-weight: bold;
font-size: 1.3em;
}
@@ -484,7 +484,7 @@
.o_address_format {
width: 100%;
.o_address_street, .o_address_country {
- @include o-flex-display;
+ display: flex;
}
.o_address_city {
@@ -559,7 +559,7 @@
// Timezone widget warning
.o_tz_warning {
- color: $brand-danger;
+ color: theme-color('danger');
cursor: help;
position: absolute;
margin-left: -40px;
@@ -675,11 +675,11 @@ label.o_light_label, .o_light_label label {
display: block;
> tr {
- @include o-flex-display;
- @include o-flex-flow(row, wrap);
+ display: flex;
+ flex-flow: row wrap;
> td {
- @include o-flex(1, 0, auto);
+ flex: 1 0 auto;
display: block;
max-width: 100%;
padding: 0;
@@ -718,9 +718,9 @@ label.o_light_label, .o_light_label label {
// Settings form views
.o_settings_container {
- @include o-flex-display;
- @include o-flex(0, 1, auto);
- @include o-flex-flow(row, wrap);
+ display: flex;
+ flex: 0 1 auto;
+ flex-flow: row wrap;
.o_setting_box:visible:nth-child(odd) {
clear: left;
}
diff --git a/addons/web/static/src/scss/form_view_extra.scss b/addons/web/static/src/scss/form_view_extra.scss
index 29c2512c1ab..cadce3f6809 100644
--- a/addons/web/static/src/scss/form_view_extra.scss
+++ b/addons/web/static/src/scss/form_view_extra.scss
@@ -75,7 +75,7 @@
.o_stat_value {
@include o-text-overflow(block);
font-weight: 700;
- color: $o-brand-primary;
+ color: $o-brand-odoo;
}
.o_stat_text {
@include o-text-overflow(block);
@@ -144,7 +144,7 @@
// Separators
.o_horizontal_separator {
- color: $o-brand-optional;
+ color: $o-brand-primary;
font-weight: bold;
}
diff --git a/addons/web/static/src/scss/import_bootstrap.scss b/addons/web/static/src/scss/import_bootstrap.scss
deleted file mode 100644
index cbd46a7afcf..00000000000
--- a/addons/web/static/src/scss/import_bootstrap.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import "bootstrap";
diff --git a/addons/web/static/src/scss/import_bootstrap_part1.scss b/addons/web/static/src/scss/import_bootstrap_part1.scss
new file mode 100644
index 00000000000..09f4d3579ac
--- /dev/null
+++ b/addons/web/static/src/scss/import_bootstrap_part1.scss
@@ -0,0 +1,11 @@
+
+// This file is importing bootstrap. While a simple "import "bootstrap";"
+// should be enough, this does not allow overridding mixins. Overridding mixins
+// is necessary for some of our need and allow to generate more efficient CSS
+// than adding more rules. This file instead copies the first part of the
+// content of the "bootstrap.scss" files to allow adding mixin overrides in
+// between.
+
+@import "functions";
+@import "variables";
+@import "mixins";
diff --git a/addons/web/static/src/scss/import_bootstrap_part2.scss b/addons/web/static/src/scss/import_bootstrap_part2.scss
new file mode 100644
index 00000000000..c15793019ad
--- /dev/null
+++ b/addons/web/static/src/scss/import_bootstrap_part2.scss
@@ -0,0 +1,40 @@
+
+// This file is importing bootstrap. While a simple "import "bootstrap";"
+// should be enough, this does not allow overridding mixins. Overridding mixins
+// is necessary for some of our need and allow to generate more efficient CSS
+// than adding more rules. This file instead copies the second part of the
+// content of the "bootstrap.scss" files to allow adding mixin overrides in
+// between.
+
+@import "root";
+@import "reboot";
+@import "type";
+@import "images";
+@import "code";
+@import "grid";
+@import "tables";
+@import "forms";
+@import "buttons";
+@import "transitions";
+@import "dropdown";
+@import "button-group";
+@import "input-group";
+@import "custom-forms";
+@import "nav";
+@import "navbar";
+@import "card";
+@import "breadcrumb";
+@import "pagination";
+@import "badge";
+@import "jumbotron";
+@import "alert";
+@import "progress";
+@import "media";
+@import "list-group";
+@import "close";
+@import "modal";
+@import "tooltip";
+@import "popover";
+@import "carousel";
+@import "utilities";
+@import "print";
diff --git a/addons/web/static/src/scss/kanban_column_progressbar.scss b/addons/web/static/src/scss/kanban_column_progressbar.scss
index 2cb35d33a2e..5f16a222736 100644
--- a/addons/web/static/src/scss/kanban_column_progressbar.scss
+++ b/addons/web/static/src/scss/kanban_column_progressbar.scss
@@ -56,16 +56,16 @@
.o_kanban_counter {
position: relative;
- @include o-flex-display;
- @include o-align-items(center);
- @include o-transition(opacity, 0.3s);
+ display: flex;
+ align-items: center;
+ transition: opacity 0.3s ease 0s;
margin-bottom: $o-kanban-record-margin*2;
> .o_kanban_counter_progress {
width: 76%;
- height: $font-size-small;
+ height: $font-size-sm;
margin-bottom: 0;
- background-color: $gray-lighter-dark;
+ background-color: gray('300');
box-shadow: none;
.progress-bar {
@@ -81,7 +81,7 @@
.o_kanban_counter_label {
font-size: 10px;
- @include user-select(none);
+ user-select: none;
}
}
@@ -91,14 +91,14 @@
color: $headings-color;
text-align: right;
white-space: nowrap;
- @include o-transform-origin(right, center);
+ transform-origin: right center;
&.o_kanban_grow {
- @include o-animation(grow, 1s, ease);
+ animation: grow 1s ease 0s 1 normal none running;
}
&.o_kanban_grow_huge {
- @include o-animation(grow_huge, 1s, ease);
+ animation: grow_huge 1s ease 0s 1 normal none running;
}
// Target currency icon
@@ -112,16 +112,16 @@
}
.o_kanban_view .o_kanban_group {
- @include o-kanban-css-filter(success, $brand-success);
- @include o-kanban-css-filter(warning, $brand-warning);
- @include o-kanban-css-filter(danger, $brand-danger);
+ @include o-kanban-css-filter(success, theme-color('success'));
+ @include o-kanban-css-filter(warning, theme-color('warning'));
+ @include o-kanban-css-filter(danger, theme-color('danger'));
&.o_kanban_group_show {
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
+ display: flex;
+ flex-flow: column nowrap;
> * {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
}
}
diff --git a/addons/web/static/src/scss/kanban_dashboard.scss b/addons/web/static/src/scss/kanban_dashboard.scss
index e6317d4f89e..3330be5bba6 100644
--- a/addons/web/static/src/scss/kanban_dashboard.scss
+++ b/addons/web/static/src/scss/kanban_dashboard.scss
@@ -1,16 +1,16 @@
.o_kanban_view.o_kanban_dashboard {
// correctly display the no_content_helper in dashboards
- @include o-flex-flow(row, wrap);
+ flex-flow: row wrap;
.o_kanban_record {
position: relative;
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
- @include o-justify-content(space-between);
+ display: flex;
+ flex-flow: column nowrap;
+ justify-content: space-between;
padding: $o-kanban-dashboard-vpadding $o-kanban-dashboard-hpadding;
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
margin-bottom: 10px;
}
@@ -41,7 +41,7 @@
}
> .o_kanban_card_manage_section {
- border-bottom: 1px solid $gray-lighter-dark;
+ border-bottom: 1px solid gray('300');
margin-bottom: 10px;
> div {
@@ -55,9 +55,9 @@
max-width: 400px;
.row {
- @include o-flex-display;
- @include o-flex-flow(row, nowrap);
- @include o-justify-content(space-between);
+ display: flex;
+ flex-flow: row nowrap;
+ justify-content: space-between;
margin-left: 0;
margin-right: 0;
padding-left: $o-kanban-dashboard-dropdown-complex-gap*2;
@@ -65,14 +65,14 @@
}
div[class*="col-"] {
- @include o-flex(1, 1, percentage(100/3));
+ flex: 1 1 percentage(100/3);
padding-left: $o-kanban-dashboard-dropdown-complex-gap;
padding-right: $o-kanban-dashboard-dropdown-complex-gap;
> .o_kanban_card_manage_title {
- margin: ($line-height-computed / 2) 0;
+ margin: (($font-size-base * $line-height-base) / 2) 0;
color: $headings-color;
- font-size: $font-size-h5;
+ font-size: $h5-font-size;
font-weight: 500;
line-height: $headings-line-height;
}
@@ -82,7 +82,7 @@
}
.row.o_kanban_card_manage_settings {
- border-top: 1px solid $gray-lighter-dark;
+ border-top: 1px solid gray('300');
padding-top: $o-kanban-dashboard-dropdown-complex-gap*3;
.oe_kanban_colorpicker {
@@ -91,7 +91,7 @@
}
div[class*="col-"] + div[class*="col-"] {
- border-left: 1px solid $gray-lighter-dark;
+ border-left: 1px solid gray('300');
}
// Default options box
@@ -137,7 +137,7 @@
// Identify subtitles without classes
.o_kanban_primary_left .o_primary > span:nth-child(2) > strong {
font-weight: 500;
- font-size: $font-size-small;
+ font-size: $font-size-sm;
color: $text-muted;
}
@@ -154,10 +154,10 @@
}
.o_kanban_card_header + .container.o_kanban_card_content {
- @include o-flex(1, 0, auto);
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
- @include o-justify-content(space-between);
+ flex: 1 0 auto;
+ display: flex;
+ flex-flow: column nowrap;
+ justify-content: space-between;
margin-top: $o-kanban-dashboard-vpadding * 2;
padding-right: 0;
padding-left: 0;
@@ -176,8 +176,8 @@
margin-bottom: -$o-kanban-dashboard-vpadding;
&.bottom_block {
- border-top: 1px solid $gray-lighter-dark;
- background-color: $gray-lighter;
+ border-top: 1px solid gray('300');
+ background-color: gray('200');
padding-top: $o-kanban-dashboard-vpadding;
padding-bottom: $o-kanban-dashboard-vpadding;
}
diff --git a/addons/web/static/src/scss/kanban_examples_dialog.scss b/addons/web/static/src/scss/kanban_examples_dialog.scss
index a42962ed8f0..65eadc9e0b4 100644
--- a/addons/web/static/src/scss/kanban_examples_dialog.scss
+++ b/addons/web/static/src/scss/kanban_examples_dialog.scss
@@ -1,17 +1,17 @@
.o_kanban_examples_dialog {
- @include o-flex-display;
+ display: flex;
padding: 0px;
- background: $o-color-silver;
+ background: theme-color('light');
// sidebar
.o_kanban_examples_dialog_nav {
- @include o-flex(0, 0, auto);
- border-right: 1px solid $gray-lighter-dark;
+ flex: 0 0 auto;
+ border-right: 1px solid gray('300');
background: white;
> ul > li {
margin: 0;
- border-bottom: 1px solid $gray-lighter-dark;
+ border-bottom: 1px solid gray('300');
> a {
padding: 12px 15px;
@@ -23,7 +23,7 @@
}
&.active > a {
color: $headings-color;
- border-left-color: $o-brand-optional;
+ border-left-color: $o-brand-primary;
font-weight: bold;
}
}
@@ -31,28 +31,28 @@
// content
.o_kanban_examples_dialog_content {
- @include o-flex(1, 1, 100%);
+ flex: 1 1 100%;
.o_kanban_examples_description {
padding: 16px 16px 0;
text-align: justify;
}
.o_kanban_examples {
- @include o-flex-display;
+ display: flex;
padding: 0 6px;
.o_kanban_examples_group {
- @include o-flex(1, 1, 100%);
+ flex: 1 1 100%;
margin: 10px;
.o_kanban_examples_ghost {
padding: 5px;
margin-top: -1px;
- border: thin solid $gray-lighter-dark;
+ border: thin solid gray('300');
background-color: white;
.o_ghost_content {
height: 12px;
- background: $gray-lighter-dark;
+ background: gray('300');
&.o_ghost_tag {
display: inline-block;
width: 40%;
diff --git a/addons/web/static/src/scss/kanban_view.scss b/addons/web/static/src/scss/kanban_view.scss
index 4d00f1be3cf..c00e5ab0d26 100644
--- a/addons/web/static/src/scss/kanban_view.scss
+++ b/addons/web/static/src/scss/kanban_view.scss
@@ -1,27 +1,27 @@
// ------- Kanban View Layout -------
.o_kanban_view {
- @include o-flex-display;
- @include o-align-content(stretch);
+ display: flex;
+ align-content: stretch;
overflow-x: visible;
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
padding: 0px!important;
overflow-x: auto;
}
.o_kanban_record, .o_kanban_quick_create {
padding: $o-kanban-inside-vgutter $o-kanban-inside-hgutter;
- border: 1px solid $gray-lighter-dark;
+ border: 1px solid gray('300');
background-color: white;
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
padding: $o-kanban-inside-vgutter $o-kanban-inside-hgutter-mobile;
}
&:focus, &:focus-within {
- -webkit-box-shadow: 1px 1px 1px 0px $gray-light;
- -moz-box-shadow: 1px 1px 1px 0px $gray-light;
- box-shadow: 1px 1px 1px 0px $gray-light;
+ -webkit-box-shadow: 1px 1px 1px 0px gray('600');
+ -moz-box-shadow: 1px 1px 1px 0px gray('600');
+ box-shadow: 1px 1px 1px 0px gray('600');
z-index: 1; // show the shadow on top of the previous & next cards in grouped mode
outline: none;
}
@@ -43,7 +43,7 @@
.o_kanban_record {
position: relative;
display: inline-block; // Force the creation of a block formatting context to clear float items
- border-color: $gray-lighter-darker;
+ border-color: gray('400');
min-width: 150px;
margin: 0 0 -1px;
@@ -61,11 +61,11 @@
}
.o_kanban_record_top, .o_kanban_record_bottom {
- @include o-flex-display;
+ display: flex;
}
.o_kanban_record_top {
- @include o-align-items(flex-start);
+ align-items: flex-start;
.o_dropdown_kanban {
// For v11 layout, reset positioning to default to properly use
@@ -77,7 +77,7 @@
.o_kanban_record_headings {
line-height: 1.2;
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
// Ensure long word doesn't break out of container
word-wrap: break-word;
overflow: hidden;
@@ -95,12 +95,12 @@
.o_kanban_record_bottom {
.oe_kanban_bottom_left, .oe_kanban_bottom_right {
- @include o-flex-display;
- @include o-align-items(center);
+ display: flex;
+ align-items: center;
height: 20px;
}
.oe_kanban_bottom_left {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
> * {
margin-right: 6px;
@@ -113,7 +113,7 @@
}
}
.oe_kanban_bottom_right{
- @include o-flex(0, 1, auto);
+ flex: 0 1 auto;
.oe_kanban_avatar {
width: 20px;
@@ -122,9 +122,9 @@
}
}
.o_link_muted {
- color: $text-color;
+ color: $body-color;
&:hover {
- color: $brand-primary;
+ color: theme-color('primary');
text-decoration: underline;
}
}
@@ -142,7 +142,7 @@
.o_dropdown_kanban {
@include o-position-absolute($o-kanban-inside-vgutter, $o-kanban-inside-hgutter);
visibility: hidden;
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
visibility: visible;
}
@@ -150,7 +150,7 @@
@include o-kanban-dropdown;
margin: (-$o-kanban-inside-vgutter - 1px) (-$o-kanban-inside-hgutter - 1px) 0 0;
}
- &.open .dropdown-toggle {
+ &.show .dropdown-toggle {
@include o-kanban-dropdown-open;
}
.dropdown-menu {
@@ -159,7 +159,7 @@
}
}
- &:hover .o_dropdown_kanban, .o_dropdown_kanban.open {
+ &:hover .o_dropdown_kanban, .o_dropdown_kanban.show {
visibility: visible;
}
@@ -207,7 +207,7 @@
> button, > a {
@include o-position-absolute($right: $o-kanban-record-margin, $bottom: $o-kanban-record-margin);
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
right: $o-kanban-inside-hgutter-mobile;
}
}
@@ -219,9 +219,9 @@
}
&.ui-sortable-helper {
- @include o-transform(rotate(-3deg));
+ transform: rotate(-3deg);
box-shadow: 0 5px 25px -10px black;
- @include transition(transform 0.6s, box-shadow 0.3s);
+ transition: transform 0.6s, box-shadow 0.3s;
}
.o_attachment_image > img {
@@ -230,18 +230,18 @@
}
.o_progressbar {
- @include o-flex-display;
+ display: flex;
height: $o-kanban-progressbar-height;
.o_progressbar_title {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
.o_progress {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
margin-top: 3px;
}
.o_progressbar_value {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
width: auto;
height: 100%;
text-align: right;
@@ -258,7 +258,7 @@
+ div {
padding-left: $o-kanban-image-width + $o-kanban-inside-hgutter;
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
padding-left: $o-kanban-image-width + $o-kanban-inside-hgutter-mobile;
}
}
@@ -270,7 +270,7 @@
margin-bottom: $o-kanban-inner-hmargin*0.5;;
padding-left: 0;
list-style: none;
- font-size: $font-size-small;
+ font-size: $font-size-sm;
li {
margin-bottom: 2px;
@@ -279,11 +279,11 @@
}
.o_kanban_footer {
- @include o-flex-display;
- @include o-justify-content(space-between);
- @include o-align-items(center);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
> * {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
}
@@ -305,7 +305,7 @@
&.o_kanban_grouped {
min-height: 100%;
padding: 0;
- background-color: $gray-lighter;
+ background-color: theme-color('light');
.o_kanban_record, .o_kanban_quick_create {
width: 100%;
@@ -320,14 +320,14 @@
// Kanban Grouped Layout - Column default
.o_kanban_group {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
padding: 0 $o-kanban-group-padding $o-kanban-group-padding $o-kanban-group-padding;
.o_kanban_header > .o_kanban_header_title {
@include o-kanban-header-title;
.o_column_title {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
@include o-text-overflow;
font-size: 16px;
font-weight: 500;
@@ -342,7 +342,7 @@
margin-left: $o-kanban-inside-hgutter*2;
}
- &:hover .o_kanban_config, .o_kanban_config.open {
+ &:hover .o_kanban_config, .o_kanban_config.show {
visibility: visible;
margin-left: $o-kanban-inside-hgutter;
}
@@ -430,7 +430,7 @@
.o_kanban_add_column {
display: inline-block;
padding: 10px 14px;
- background-color: $o-color-silver-dark;
+ background-color: gray('300');
}
.o_kanban_title {
margin-left: 10px;
@@ -443,7 +443,7 @@
height: 100%;
border: none;
box-shadow: 0 0 20px -10px;
- background-color: $gray-lighter;
+ background-color: theme-color('light');
.o_kanban_header {
height: 50px;
@@ -453,18 +453,13 @@
}
input, input:focus, input:hover {
- margin-top: 3px;
font-size: 16px;
background: transparent;
}
-
- .o_kanban_add {
- margin-left: 10px;
- }
}
.o_kanban_muted_record {
- background: $gray-lighter-dark;
+ background: gray('300');
height: 70px;
margin: 10px 0px;
}
@@ -474,19 +469,19 @@
// Kanban UN-grouped Layout
&.o_kanban_ungrouped {
- @include o-flex-flow(row, wrap);
- @include o-justify-content(flex-start);
+ flex-flow: row wrap;
+ justify-content: flex-start;
padding: $o-kanban-record-margin ($o-horizontal-padding - $o-kanban-record-margin);
.o_kanban_record {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
width: $o-kanban-default-record-width;
margin: ($o-kanban-record-margin * 0.5) $o-kanban-record-margin;
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
margin: 0 0 -1px 0;
- @include o-flex(1, 0, 100%);
+ flex: 1 0 100%;
}
&.o_kanban_ghost {
diff --git a/addons/web/static/src/scss/kanban_view_mobile.scss b/addons/web/static/src/scss/kanban_view_mobile.scss
index ed4e6ad8436..b74ae8aaea5 100644
--- a/addons/web/static/src/scss/kanban_view_mobile.scss
+++ b/addons/web/static/src/scss/kanban_view_mobile.scss
@@ -1,4 +1,4 @@
-@media (max-width: $screen-xs-max) {
+@include media-breakpoint-down(sm) {
.o_kanban_view.o_kanban_grouped {
display: block;
position: relative;
@@ -11,7 +11,7 @@
.o_kanban_mobile_tab {
@include o-position-absolute($left: 100%);
- @include o-transform(translateX(-50%));
+ transform: translateX(-50%);
height: $o-kanban-mobile-tabs-height;
padding: 10px;
font-size: 14px;
@@ -19,7 +19,7 @@
&.o_current {
font-weight: bold;
- border-bottom: 3px solid $o-brand-optional;
+ border-bottom: 3px solid $o-brand-primary;
}
.o_column_title {
white-space: nowrap;
diff --git a/addons/web/static/src/scss/layout_background.scss b/addons/web/static/src/scss/layout_background.scss
index e23b2585b50..400ba12789b 100644
--- a/addons/web/static/src/scss/layout_background.scss
+++ b/addons/web/static/src/scss/layout_background.scss
@@ -1,9 +1,9 @@
.o_background_footer, .o_background_header, .o_report_layout_background {
font-family: 'Lato';
- color: $gray;
+ color: gray('700');
}
.o_background_header {
- border-bottom: 1px solid $gray-lighter;
+ border-bottom: 1px solid gray('200');
.company_address {
min-width: 300px;
}
@@ -13,19 +13,19 @@
margin-right: 16px;
}
h3 {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
font-weight: 700;
max-width: 300px;
}
}
.o_background_footer {
ul {
- border-top: 1px solid $o-brand-primary;
- border-bottom: 1px solid $o-brand-primary;
+ border-top: 1px solid $o-brand-odoo;
+ border-bottom: 1px solid $o-brand-odoo;
padding: 4px 0;
margin: 0 0 4px 0;
li {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
}
}
}
@@ -36,10 +36,10 @@
background-repeat: no-repeat;
min-height: 900px;
thead tr th, h2 {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
}
tbody {
- color: $gray;
+ color: gray('700');
tr:nth-child(odd) {
background-color: rgba(184, 171, 180, 0.2);
}
@@ -48,7 +48,7 @@
}
}
/*Total table*/
- .row > .col-xs-4 > table {
+ .row > .col-4 > table {
tr:nth-child(odd) {
background-color: transparent !important;
}
@@ -57,7 +57,7 @@
border-top: none !important;
}
tr:last-child td {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
}
}
#total {
diff --git a/addons/web/static/src/scss/layout_boxed.scss b/addons/web/static/src/scss/layout_boxed.scss
index 92208945f45..426b3dd2aac 100644
--- a/addons/web/static/src/scss/layout_boxed.scss
+++ b/addons/web/static/src/scss/layout_boxed.scss
@@ -1,10 +1,10 @@
.o_boxed_footer, .o_boxed_header, .o_report_layout_boxed {
font-family: 'Lato';
- color: $gray;
+ color: gray('700');
font-size: 12px;
}
.o_boxed_header {
- border-bottom: 1px solid $gray-lighter;
+ border-bottom: 1px solid gray('200');
img {
max-height: 100px;
}
@@ -17,7 +17,7 @@
.o_boxed_footer {
margin-top: 200px;
white-space: nowrap;
- border-top: 3px solid $gray;
+ border-top: 3px solid gray('700');
ul {
margin: 4px 0;
}
@@ -26,7 +26,7 @@
// This is not a general rule since the id is not used in all the reports,
// we should make a general structure for report body to use it everywhere
#informations {
- border: 1px solid $gray;
+ border: 1px solid gray('700');
padding-top: 10px;
margin: 0;
}
@@ -34,28 +34,28 @@
text-transform: uppercase;
}
table {
- border: 1px solid $gray;
+ border: 1px solid gray('700');
thead {
tr th {
- border-bottom: 3px solid $gray !important;
+ border-bottom: 3px solid gray('700') !important;
text-transform: uppercase;
}
}
tbody {
- color: $gray;
+ color: gray('700');
tr {
td {
border-top: none;
- border-right: 1px solid $gray;
+ border-right: 1px solid gray('700');
}
td:last-child {
- background-color: $gray-lighter;
+ background-color: gray('200');
}
}
}
}
/*Total table*/
- .row > .col-xs-4 > table {
+ .row > .col-4 > table {
td {
border-right: none;
}
@@ -67,7 +67,7 @@
background-color: transparent;
}
tr:last-child td {
- background-color: $gray;
+ background-color: gray('700');
color: #fff;
}
}
diff --git a/addons/web/static/src/scss/layout_clean.scss b/addons/web/static/src/scss/layout_clean.scss
index 64ec2fd5245..06b2e808dd4 100644
--- a/addons/web/static/src/scss/layout_clean.scss
+++ b/addons/web/static/src/scss/layout_clean.scss
@@ -12,16 +12,16 @@
.o_clean_footer {
margin: 0 3px;
margin-top: 200px;
- border-top: 3px solid $o-brand-primary;
+ border-top: 3px solid $o-brand-odoo;
h4 {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
font-weight: bolder;
}
.pagenumber {
width: 35px;
height: 35px;
- border: 3px solid $o-brand-primary;
- background-color: $o-brand-optional;
+ border: 3px solid $o-brand-odoo;
+ background-color: $o-brand-primary;
color: white;
padding-top: 6px;
text-align: center;
@@ -29,17 +29,17 @@
}
.o_report_layout_clean {
h1, h2, h3 {
- color: $o-brand-optional;
+ color: $o-brand-primary;
font-weight: bolder;
}
strong {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
}
table {
thead {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
tr th {
- border-top: 3px solid $o-brand-primary !important;
+ border-top: 3px solid $o-brand-odoo !important;
text-transform: uppercase;
}
tr th:last-child {
@@ -54,7 +54,7 @@
border-top: none;
}
tr:last-child td {
- border-bottom: 3px solid $o-brand-primary;
+ border-bottom: 3px solid $o-brand-odoo;
}
tr {
td {
@@ -66,13 +66,13 @@
}
}
/*Total table*/
- .row > .col-xs-4 {
+ .row > .col-4 {
width: 43%;
position: relative;
top: -20px;
> table {
tr:last-child td {
- border-top: 1px solid $gray-lighter !important;
+ border-top: 1px solid gray('200') !important;
}
tr:first-child td {
/*we could get rid of this rule if .border-black td would be terminated in report.scss*/
diff --git a/addons/web/static/src/scss/list_view.scss b/addons/web/static/src/scss/list_view.scss
index 27c10cda556..ba5cd8a4dab 100644
--- a/addons/web/static/src/scss/list_view.scss
+++ b/addons/web/static/src/scss/list_view.scss
@@ -5,10 +5,15 @@
background-color: $o-view-background-color;
margin-bottom: 0px;
+ // Don't understand why but without those, the list view appears broken
+ // in both form views and standalone list views.
+ border-collapse: initial;
+ border-spacing: 0;
+
// Checkbox in editable list
// should be clickable and activate the row
&.o_editable_list .o_data_row:not(.o_selected_row) .o_data_cell {
- .o_checkbox:not(.o_readonly_modifier) {
+ .custom-checkbox:not(.o_readonly_modifier) {
pointer-events: none;
}
}
@@ -41,7 +46,7 @@
.o_column_sortable {
position: relative;
- @include user-select(none); // Prevent unwanted selection while sorting
+ user-select: none; // Prevent unwanted selection while sorting
&::after {
font-family: FontAwesome;
@@ -96,11 +101,12 @@
}
.o_group_pager {
cursor: text;
- @include user-select(none);
+ user-select: none;
text-align: right;
- padding-top: 0;
- padding-bottom: 0;
+ padding-top: 0 !important;
+ padding-bottom: 0 !important;
.o_pager_previous, .o_pager_next {
+ max-height: 30px;
background-color: $o-list-group-header-color;
&:hover {
background-color: darken($o-list-group-header-color, 10%);
@@ -182,7 +188,7 @@
width: 16px; // to have some space on the right
}
.o_input {
- padding: $table-condensed-cell-padding;
+ padding: $table-cell-padding-sm;
background-color: white;
.o_input {
diff --git a/addons/web/static/src/scss/list_view_extra.scss b/addons/web/static/src/scss/list_view_extra.scss
index ec53efc6df5..83791ce42dd 100644
--- a/addons/web/static/src/scss/list_view_extra.scss
+++ b/addons/web/static/src/scss/list_view_extra.scss
@@ -5,6 +5,6 @@
}
tbody > tr.o_group_header {
- @include o-vertical-gradient(#fcfcfc, #dedede);
+ background-image: linear-gradient(to bottom, #fcfcfc, #dedede);
}
}
diff --git a/addons/web/static/src/scss/modal.scss b/addons/web/static/src/scss/modal.scss
index 82faabfa3bc..5dc3c1eb7d0 100644
--- a/addons/web/static/src/scss/modal.scss
+++ b/addons/web/static/src/scss/modal.scss
@@ -31,7 +31,7 @@
}
- @media (min-width: $screen-sm-min) {
+ @include media-breakpoint-up(md) {
.modal-dialog {
height: 100%;
padding: 30px 0;
@@ -39,11 +39,11 @@
.modal-content {
max-height: 100%;
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
+ display: flex;
+ flex-flow: column nowrap;
.modal-header, .modal-footer {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
.modal-body {
@@ -54,15 +54,15 @@
&.o_dialog_error {
overflow: visible;
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
+ display: flex;
+ flex-flow: column nowrap;
> .alert, > button {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
> .o_error_detail {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
min-height: 0;
overflow: auto;
}
diff --git a/addons/web/static/src/scss/model_field_selector.scss b/addons/web/static/src/scss/model_field_selector.scss
index 0eec3e60049..1acd3b0cc90 100644
--- a/addons/web/static/src/scss/model_field_selector.scss
+++ b/addons/web/static/src/scss/model_field_selector.scss
@@ -3,9 +3,9 @@
position: relative;
> .o_field_selector_value {
- @include o-flex-display;
- @include o-flex-flow(row, wrap);
- @include o-align-items(center);
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
height: 100%;
min-height: 20px; // needed when there is no value in it and used standalone
&:active, &:focus, &:active:focus {
@@ -19,15 +19,15 @@
margin-bottom: 1px;
}
> i {
- @include o-align-self(center);
+ align-self: center;
margin: 0 2px;
font-size: 10px;
}
}
> .o_field_selector_controls {
@include o-position-absolute(0, 0, 1px);
- @include o-flex-display;
- @include o-align-items(center);
+ display: flex;
+ align-items: center;
cursor: pointer;
}
@@ -51,7 +51,7 @@
.o_field_selector_popover_header {
color: white;
- background: $brand-primary;
+ background: theme-color('primary');
font-weight: bold;
padding: 5px 0 5px 0.4em;
@@ -67,14 +67,14 @@
&.o_prev_page {
left: 0;
- border-right: 1px solid darken($brand-primary, 10%);
+ border-right: 1px solid darken(theme-color('primary'), 10%);
}
&.o_field_selector_close {
right: 0;
- border-left: 1px solid darken($brand-primary, 10%);
+ border-left: 1px solid darken(theme-color('primary'), 10%);
}
&:hover {
- background: darken($brand-primary, 10%);
+ background: darken(theme-color('primary'), 10%);
}
}
&:before {
@@ -82,7 +82,7 @@
content: "";
border-left: $o-field-selector-arrow-height solid rgba(0, 0, 0, 0);
border-right: $o-field-selector-arrow-height solid rgba(0, 0, 0, 0);
- border-bottom: $o-field-selector-arrow-height solid $brand-primary;
+ border-bottom: $o-field-selector-arrow-height solid theme-color('primary');
}
}
.o_field_selector_popover_body {
@@ -110,15 +110,15 @@
}
.o_field_selector_relation_icon {
@include o-position-absolute($top: 0, $right: 0, $bottom: 0);
- @include o-flex-display;
- @include o-align-items(center);
+ display: flex;
+ align-items: center;
padding: 10px;
}
}
}
}
.o_field_selector_popover_footer {
- background: $brand-primary;
+ background: theme-color('primary');
padding: 5px 0.4em;
> input {
diff --git a/addons/web/static/src/scss/navbar.scss b/addons/web/static/src/scss/navbar.scss
index 770532d6693..aa1a2c23067 100644
--- a/addons/web/static/src/scss/navbar.scss
+++ b/addons/web/static/src/scss/navbar.scss
@@ -3,7 +3,7 @@
position: relative;
height: $o-navbar-height;
border-bottom: 1px solid $o-navbar-inverse-link-hover-bg;
- background-color: $o-brand-primary;
+ background-color: $o-brand-odoo;
color: white;
> a, > button {
@@ -17,7 +17,7 @@
color: inherit;
font-size: 18px;
- @include user-select(none);
+ user-select: none;
&:hover, &:focus {
background-color: $o-navbar-inverse-link-hover-bg;
@@ -32,13 +32,13 @@
display: block;
float: left;
margin-right: 35px;
- @include user-select(none);
+ user-select: none;
color: white;
font-size: 22px;
font-weight: 500;
line-height: $o-navbar-height;
- @media (max-width: $screen-sm-max) {
+ @include media-breakpoint-down(md) {
float: none;
margin: 0;
border-bottom: 1px solid $o-navbar-inverse-link-hover-bg;
@@ -86,21 +86,21 @@
width: $o-navbar-height;
text-align: center;
}
- &.open > ul {
+ &.show > ul {
padding: 0;
> li {
> a {
- background-color: $o-brand-primary;
+ background-color: $o-brand-odoo;
color: white;
border-bottom: 1px solid $o-brand-lightsecondary;
&.dropdown-toggle {
- background-color: lighten($o-brand-primary, 15%);
+ background-color: lighten($o-brand-odoo, 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
+ > .dropdown-menu { // remove dropdown-menu default style as it is nested in another one
position: static;
float: none;
display: block;
@@ -115,27 +115,23 @@
&.o_menu_systray {
float: right;
- .open .dropdown-menu {
- left: auto;
- right: 0;
- }
}
}
- .open .dropdown-menu {
+ .dropdown-menu.show {
max-height: 90vh; // the dropdown should not overstep the viewport
min-width: 100%;
overflow: auto;
margin-top: 0;
@for $index from 3 through 5 {
- > li.o_menu_header_lvl_#{$index}, > li .o_menu_entry_lvl_#{$index} {
+ .o_menu_header_lvl_#{$index}, .o_menu_entry_lvl_#{$index} {
padding-left: $o-dropdown-hpadding + ($index - 2)*12px;
}
}
}
- .open .dropdown-toggle {
+ .show .dropdown-toggle {
background-color: $o-navbar-inverse-link-hover-bg;
}
.o_user_menu {
@@ -147,12 +143,12 @@
.oe_topbar_avatar {
height: 17px;
- @include o-transform(translateY(-2px));
+ transform: translateY(-2px);
}
}
- @media (max-width: $screen-sm-max) {
- @include o-transition(height, 200ms, linear);
+ @include media-breakpoint-down(md) {
+ transition: height 200ms linear 0s;
position: relative;
height: $o-navbar-height;
@@ -165,7 +161,7 @@
display: none;
}
- &.open .dropdown-menu {
+ .dropdown-menu.show {
max-height: none;
}
}
@@ -173,7 +169,7 @@
&.o_menu_sections {
width: 100%;
- > li.open .dropdown-menu {
+ .dropdown-menu.show {
position: static;
float: none;
background-color: transparent;
@@ -181,7 +177,7 @@
border: none;
overflow: visible;
- > li > a {
+ > .dropdown-item {
background-color: transparent;
color: inherit;
}
@@ -196,7 +192,7 @@
> li {
display: inline-block;
- &.open .dropdown-menu {
+ .dropdown-menu.show {
@include o-position-absolute($o-navbar-height, 0, 0, 0);
position: fixed;
width: auto;
@@ -211,7 +207,7 @@
}
}
-@media (max-width: $screen-sm-max) {
+@include media-breakpoint-down(md) {
body.o_mobile_menu_opened {
overflow: hidden;
height: 100%;
@@ -224,11 +220,11 @@
}
}
-@media (max-width: $screen-sm-max) {
- .o_switch_company_menu > .dropdown-menu {
- padding-top: 0px;
- li.bg-info {
- padding: 10px;
- }
- }
- }
+@include media-breakpoint-down(md) {
+ .o_switch_company_menu > .dropdown-menu {
+ padding-top: 0px;
+ .bg-info {
+ padding: 10px;
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/pivot_view.scss b/addons/web/static/src/scss/pivot_view.scss
index 3efddd8eab2..d10c4997f43 100644
--- a/addons/web/static/src/scss/pivot_view.scss
+++ b/addons/web/static/src/scss/pivot_view.scss
@@ -5,7 +5,7 @@
// items corresponding to the clicked cell
&.o_enable_linking {
.o_pivot_cell_value:hover {
- color: $o-brand-optional;
+ color: $o-brand-primary;
cursor: pointer;
}
}
@@ -23,7 +23,7 @@
background-color: lighten($o-brand-secondary, 40%);
cursor: pointer;
white-space: nowrap;
- @include user-select(none);
+ user-select: none;
&:hover {
background-color: lighten($o-brand-secondary, 30%);
}
diff --git a/addons/web/static/src/scss/primary_variables.scss b/addons/web/static/src/scss/primary_variables.scss
index b394aeafe26..0f7f43411c4 100644
--- a/addons/web/static/src/scss/primary_variables.scss
+++ b/addons/web/static/src/scss/primary_variables.scss
@@ -4,20 +4,21 @@
///
// Font sizes
-$o-font-size-base: 13px;
-$o-line-height-base: 1.428571429; // This is BS default
+$o-root-font-size: 13px;
+$o-font-size-base: 1rem;
+$o-line-height-base: 1.5; // This is BS default
// Colors
-$o-brand-primary: #7c7bad;
-$o-brand-optional: #7c7bad;
+$o-community-color: #7C7BAD;
+$o-enterprise-color: #875A7B;
+
+$o-brand-odoo: $o-community-color;
+$o-brand-primary: $o-community-color;
+
$o-brand-secondary: #f0eeee;
$o-brand-lightsecondary: #e2e2e0;
-$o-color-silver: #F9F9F9;
-$o-color-silver-dark: #E5E5E5;
-$o-color-silver-darker: #d9d7d7;
-$o-color-gray-light: lighten(#000, 46.7%); // This is BS default
+$o-gray-100: #f8f9fa; // This is BS default
-$o-color-pink: #875A7B; // Enterprise $o-brand-primary
$o-main-color-muted: #a8a8a8;
$o-main-text-color: #4c4c4c;
@@ -36,8 +37,21 @@ $o-tooltip-text-color: #777777;
$o-tooltip-title-text-color: #4c4c4c;
// Layout
-$screen-xs-min: 475px;
-$screen-xl-min: 1534px;
+//
+// Extension of BS4. This is not redefining the BS4 variable directly as we only
+// need the extra ones for media queries (not creating new breakpoint classes).
+// Note: default BS4 values are hardcoded here while it should be possible to
+// merge with the default BS variable (but we would have to take care of
+// ordering & cie).
+$o-extra-grid-breakpoints: (
+ xs: 0,
+ vsm: 475px,
+ sm: 576px,
+ md: 768px,
+ lg: 992px,
+ xl: 1200px,
+ xxl: 1534px,
+);
$o-form-group-cols: 12;
$o-form-spacing-unit: 5px;
diff --git a/addons/web/static/src/scss/progress_bar.scss b/addons/web/static/src/scss/progress_bar.scss
index 8aaade8812f..71af77082f6 100644
--- a/addons/web/static/src/scss/progress_bar.scss
+++ b/addons/web/static/src/scss/progress_bar.scss
@@ -23,7 +23,7 @@
}
.o_progressbar_complete {
- background-color: $o-brand-optional;
+ background-color: $o-brand-primary;
height: 100%;
}
}
diff --git a/addons/web/static/src/scss/rainbow.scss b/addons/web/static/src/scss/rainbow.scss
index 8a705242adc..fa666fca246 100644
--- a/addons/web/static/src/scss/rainbow.scss
+++ b/addons/web/static/src/scss/rainbow.scss
@@ -10,31 +10,31 @@
z-index: $zindex-modal;
padding: 50px;
margin: -5% auto 0 (-$reward-size / 2);
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
margin: -5% auto 0 (-$reward-size-mobile / 2);
}
background-image: -webkit-radial-gradient(#EDEFF4 30%, transparent 70%, transparent);
background-image: -o-radial-gradient(#EDEFF4 30%, transparent 70%, transparent);
background-image: radial-gradient(#EDEFF4 30%, transparent 70%, transparent);
- @include o-animation(reward-fading, $reward-base-time * 0.5, ease-in-out, 0s, 1, normal, forwards);
+ animation: reward-fading ($reward-base-time * 0.5) ease-in-out 0s 1 normal forwards;
@include o-position-absolute(20%, auto, auto, 50%);
@include size($reward-size, $reward-size);
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
@include size($reward-size-mobile, $reward-size-mobile);
}
&.o_reward_fading {
display: block;
- @include o-animation(reward-fading-reverse, ($reward-base-time * 0.4), ease-in-out, 0s, 1, normal, forwards);
+ animation: reward-fading-reverse ($reward-base-time * 0.4) ease-in-out 0s 1 normal forwards;
.o_reward_face_group {
- @include o-animation(reward-jump-reverse, ($reward-base-time * 0.4), ease-in-out, 0s, 1, normal, forwards);
+ animation: reward-jump-reverse ($reward-base-time * 0.4) ease-in-out 0s 1 normal forwards;
}
.o_reward_rainbow {
path {
- @include o-animation(reward-rainbow-reverse, ($reward-base-time * 0.5), ease-out, 0s, 1, normal, forwards);
+ animation: reward-rainbow-reverse ($reward-base-time * 0.5) ease-out 0s 1 normal forwards;
}
}
@@ -51,13 +51,13 @@
fill: none;
stroke-linecap: round;
stroke-width: 21px;
- @include o-animation(reward-rainbow, ($reward-base-time ), ease-out, 0s, 1, normal, forwards);
+ animation: reward-rainbow $reward-base-time ease-out 0s 1 normal forwards;
}
}
.o_reward_face_group {
transform-origin: center;
- @include o-animation(reward-jump, $reward-base-time * 0.8, ease-in-out);
+ animation: reward-jump $reward-base-time * 0.8 ease-in-out 0s 1 normal none running;
@include o-position-absolute(6%, 0, 0, 0);
@include size(100%, 60%);
}
@@ -68,14 +68,14 @@
position: relative;
border-radius: 100%;
background: center center / contain no-repeat;
- @include o-animation(reward-float, $reward-base-time, ease-in-out, $reward-base-time, infinite, alternate);
+ animation: reward-float $reward-base-time ease-in-out $reward-base-time infinite alternate;
@include size(34%, 56.67%);
}
.o_reward_stars {
display: block;
@include size($reward-size * 0.75, $reward-size / 2);
- @media (max-width: $screen-xs-max) {
+ @include media-breakpoint-down(sm) {
@include size($reward-size-mobile * 0.75, $reward-size-mobile / 2);
}
@include o-position-absolute(18%, 7%);
@@ -83,10 +83,10 @@
svg {
transform-origin: center center;
@include o-position-absolute(28%, $left:3%);
- @include o-animation(reward-stars, $reward-base-time, ease-in-out, 0s, infinite, alternate-reverse);
+ animation: reward-stars $reward-base-time ease-in-out 0s infinite alternate-reverse;
&.star2, &.star4 {
- @include o-animation(reward-stars, ($reward-base-time*1.2), ease-in-out, 0s, infinite, alternate);
+ animation: reward-stars ($reward-base-time*1.2) ease-in-out 0s infinite alternate;
}
&.star2 {
@@ -110,7 +110,7 @@
.o_reward_thumbup {
width: 40px;
display: block;
- @include o-animation(reward-scale, $reward-base-time * 0.5, ease-in-out, 0s, infinite, alternate);
+ animation: reward-scale ($reward-base-time * 0.5) ease-in-out 0s infinite alternate;
@include o-position-absolute(63%, auto, auto, 65%);
}
@@ -121,9 +121,9 @@
margin-left: 15%;
// Translate before animate
- @include o-transform(translateY(5px));
+ transform: translateY(5px);
- @include o-animation(reward-float, $reward-base-time, ease-in-out, $reward-base-time, infinite, alternate-reverse);
+ animation: reward-float $reward-base-time ease-in-out $reward-base-time infinite alternate-reverse;
@include o-position-absolute(85%, auto, auto, 0%);
.o_reward_thumb_right {
@@ -155,16 +155,16 @@
}
.o_reward_shadow_container {
- @include o-transform(translateY(0px) rotateZ(0));
- @include o-animation(reward-float, $reward-base-time, ease-in-out, $reward-base-time, infinite, alternate);
+ transform: translateY(0px) rotateZ(0);
+ animation: reward-float $reward-base-time ease-in-out $reward-base-time infinite alternate;
}
.o_reward_shadow {
@include size(100%, 12px);
background-color: #e7eaf0;
border-radius: 100%;
- @include o-transform(scale(0.8) rotateZ(0));
- @include o-animation(reward-scale, $reward-base-time, ease-in-out, $reward-base-time, infinite, alternate);
+ transform: scale(0.8) rotateZ(0);
+ animation: reward-scale $reward-base-time ease-in-out $reward-base-time infinite alternate;
@include o-position-absolute(auto, auto, -40px, 0);
}
}
@@ -187,25 +187,25 @@
@keyframes reward-jump {
0% {
- @include o-transform(scale(0.5));
+ transform: scale(0.5);
}
50% {
- @include o-transform(scale(1.05));
+ transform: scale(1.05);
}
to {
- @include o-transform(scale(1));
+ transform: scale(1);
}
}
@keyframes reward-jump-reverse {
0% {
- @include o-transform(scale(1));
+ transform: scale(1);
}
50% {
- @include o-transform(scale(1.05));
+ transform: scale(1.05);
}
to {
- @include o-transform(scale(0.5));
+ transform: scale(0.5);
}
}
@@ -226,30 +226,30 @@
@keyframes reward-float {
from {
- @include o-transform(translateY(0px));
+ transform: translateY(0px);
}
to {
- @include o-transform(translateY(5px));
+ transform: translateY(5px);
}
}
@keyframes reward-stars {
from {
- @include o-transform(scale(0.3) rotate(0deg));
+ transform: scale(0.3) rotate(0deg);
}
50% {
- @include o-transform(scale(1.0) rotate(20deg));
+ transform: scale(1.0) rotate(20deg);
}
to {
- @include o-transform(scale(0.3) rotate(80deg));
+ transform: scale(0.3) rotate(80deg);
}
}
@keyframes reward-scale {
from {
- @include o-transform(scale(0.8));
+ transform: scale(0.8);
}
to {
- @include o-transform(scale(1.0));
+ transform: scale(1.0);
}
}
diff --git a/addons/web/static/src/scss/report.scss b/addons/web/static/src/scss/report.scss
index a2df1fbc69b..cce5c6d3be5 100644
--- a/addons/web/static/src/scss/report.scss
+++ b/addons/web/static/src/scss/report.scss
@@ -11,7 +11,7 @@ body {
}
/* See https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1524 */
-.table-condensed {
+.table-sm {
> thead > tr > th {
border-bottom: none !important;
}
@@ -30,7 +30,7 @@ body {
}
/* Wkhtmltopdf doesn't support very well the media-print CSS (depends on the version) */
-.hidden-print{
+.d-print-none{
display: none;
}
diff --git a/addons/web/static/src/scss/search_groupby_menu.scss b/addons/web/static/src/scss/search_groupby_menu.scss
deleted file mode 100644
index 4092b4b5fb7..00000000000
--- a/addons/web/static/src/scss/search_groupby_menu.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-// Group By
-.o_group_by_menu {
- @include o-selected-li;
-
- max-height: calc(100vh - 125px);
- overflow: auto;
-
- .o_add_group { // add button
- @include o-search-options-dropdown-custom-li;
- }
-
- .o_submenu_switcher {
- position: absolute;
- right: 0px;
- }
-}
diff --git a/addons/web/static/src/scss/search_view.scss b/addons/web/static/src/scss/search_view.scss
index 0ff5fd320e7..700c13f7e84 100644
--- a/addons/web/static/src/scss/search_view.scss
+++ b/addons/web/static/src/scss/search_view.scss
@@ -1,11 +1,10 @@
-@mixin o-search-options-dropdown-custom-li {
- margin: 3px 25px;
+@mixin o-search-options-dropdown-custom-item {
width: auto;
max-width: 250px;
}
.o_searchview {
- @include o-align-items(flex-end);
+ align-items: flex-end;
position: relative;
padding: 0 20px 1px 0;
@@ -15,25 +14,25 @@
}
.o_searchview_input_container {
- @include o-flex-display;
- @include o-flex-flow(row, wrap);
+ display: flex;
+ flex-flow: row wrap;
.o_searchview_facet {
$o-searchview-facet-remove-width: 18px;
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
max-width: 100%;
- @include o-flex-display;
+ display: flex;
position: relative;
margin: 1px 3px 0 0;
.o_searchview_facet_label {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
@include o-text-overflow;
padding: 0 3px;
color: white;
- @include o-flex-display;
- @include o-align-items(center);
+ display: flex;
+ align-items: center;
}
.o_facet_values {
@@ -43,10 +42,10 @@
}
}
.o_facet_remove {
- @include o-flex(0, 0, auto);
- @include o-flex-display;
- @include o-justify-content(center);
- @include o-align-items(center);
+ flex: 0 0 auto;
+ display: flex;
+ justify-content: center;
+ align-items: center;
@include o-position-absolute(0, 0, 0);
width: $o-searchview-facet-remove-width;
cursor: pointer;
@@ -54,7 +53,7 @@
}
.o_searchview_input {
width: 100px;
- @include o-flex(1, 0, auto);
+ flex: 1 0 auto;
}
.o_searchview_more {
@@ -107,7 +106,7 @@
display: inline-block;
cursor: pointer;
- @include user-select(none); // Prevent text selection when toggling the dropdowns
+ user-select: none; // Prevent text selection when toggling the dropdowns
> a { // dropdown togglers
color: $o-main-text-color;
&:hover {
@@ -116,7 +115,7 @@
color: darken($o-main-text-color, 10%);
}
}
- &.open > a {
+ &.show > a {
font-weight: bold;
color: darken($o-main-text-color, 10%);
}
@@ -130,7 +129,7 @@
a:before {
@include o-caret-right;
@include o-position-absolute($top: 50%, $left: 10px);
- margin-top: (-$caret-width-base);
+ margin-top: (-$caret-width);
}
}
.o_open_menu {
@@ -138,7 +137,7 @@
a:before {
@include o-caret-down;
@include o-position-absolute($top: 50%, $left: 10px);
- margin-top: (-$caret-width-base);
+ margin-top: (-$caret-width);
}
}
@@ -150,7 +149,7 @@
overflow: auto;
.o_filter_condition {
- @include o-search-options-dropdown-custom-li;
+ @include o-search-options-dropdown-custom-item;
margin-bottom: 8px;
.o_or_filter { // or between conditions
display: none; // hidden for the first condition
@@ -177,7 +176,7 @@
}
.o_add_filter_menu { // apply and add buttons
display: none; // Needed by the webclient
- @include o-search-options-dropdown-custom-li;
+ @include o-search-options-dropdown-custom-item;
}
.o_submenu_switcher {
position: absolute;
@@ -196,7 +195,7 @@
max-height: calc(100vh - 125px);
overflow: auto;
- .divider {display: none;} // hide the divider by default (no favorite)
+ .dropdown-divider {display: none;} // hide the divider by default (no favorite)
.o-searchview-custom-private, .o-searchview-custom-public {
.o-remove-filter {
@include o-position-absolute(50%, 12px);
@@ -212,6 +211,6 @@
}
.o_save_name { // save button
display: none; // hidden by default
- @include o-search-options-dropdown-custom-li;
+ @include o-search-options-dropdown-custom-item;
}
}
diff --git a/addons/web/static/src/scss/search_view_extra.scss b/addons/web/static/src/scss/search_view_extra.scss
index d2098a5f9c3..1deba51bfba 100644
--- a/addons/web/static/src/scss/search_view_extra.scss
+++ b/addons/web/static/src/scss/search_view_extra.scss
@@ -1,21 +1,21 @@
.o_searchview {
background-color: white;
border: 1px solid #ccc;
- border-radius: $border-radius-base;
+ border-radius: $border-radius;
padding: 1px 25px 3px 5px;
.o_searchview_facet {
- border: 1px solid $gray-light;
- background: lighten($o-brand-primary, 35%);
+ border: 1px solid gray('600');
+ background: lighten($o-brand-odoo, 35%);
.o_searchview_facet_label {
- background-color: $gray-light;
+ background-color: gray('600');
}
.o_facet_remove {
- color: $gray-light;
+ color: gray('600');
&:hover {
- color: $gray;
+ color: gray('700');
}
}
}
@@ -28,7 +28,7 @@
@include o-position-absolute($top: 6px, $right: 5px);
}
.o_searchview_autocomplete li.o-selection-focus {
- background-color: $o-brand-primary;
+ background-color: $o-brand-odoo;
> a {
color: white;
}
diff --git a/addons/web/static/src/scss/search_view_mobile.scss b/addons/web/static/src/scss/search_view_mobile.scss
index c36f5d39850..f5ccd133cc1 100644
--- a/addons/web/static/src/scss/search_view_mobile.scss
+++ b/addons/web/static/src/scss/search_view_mobile.scss
@@ -48,7 +48,7 @@
.o_dropdown {
width: 100%;
margin: 15px 5px 0px 5px;
- border: solid 1px darken($gray-lighter, 20%);
+ border: solid 1px darken(gray('200'), 20%);
}
.o_dropdown_toggler_btn {
@@ -66,7 +66,7 @@
width: 100%;
box-shadow: none;
border: none;
- color: $gray-light;
+ color: gray('600');
.divider {
margin: 0px;
}
@@ -85,4 +85,4 @@
z-index: 1000;
}
}
-} \ No newline at end of file
+}
diff --git a/addons/web/static/src/scss/secondary_variables.scss b/addons/web/static/src/scss/secondary_variables.scss
index 8ab2d5bc322..ee7f15eded6 100644
--- a/addons/web/static/src/scss/secondary_variables.scss
+++ b/addons/web/static/src/scss/secondary_variables.scss
@@ -1,30 +1,21 @@
-// Define $gray-lighter-dark as a minor bootstrap $gray-lighter variation used
-// for design purposes only (e.g. cards' borders). We avoid to overwrite the
-// default $gray-light because it is deeply used by bootstrap to define muted
-// elements.
-$gray-lighter-dark: $o-color-silver-dark;
-$gray-lighter-darker: $o-color-silver-darker;
-
-$o-webclient-background-color: $o-color-silver;
-$o-control-panel-background-color: $o-color-silver;
+$o-webclient-background-color: $o-gray-100;
+$o-control-panel-background-color: $o-gray-100;
$o-list-footer-color: $o-main-text-color;
$o-list-group-header-color: lighten($o-brand-lightsecondary, 10%);
// UI custom colors for tags, kanban records' colors, ...)
-$o-colors: $o-color-gray-light, #F06050, #F4A460, #F7CD1F, #6CC1ED, #814968,
+// Note: the first value is the old BS3 gray-light value
+$o-colors: lighten(#000, 46.7%), #F06050, #F4A460, #F7CD1F, #6CC1ED, #814968,
#EB7E7F, #2C8397, #475577, #D6145F, #30C381, #9365B8;
-$screen-xxs-max: ($screen-xs-min - 1);
-$screen-lg-max: ($screen-xl-min - 1);
-
$o-sheet-cancel-hpadding: $o-horizontal-padding;
$o-sheet-cancel-bpadding: $o-horizontal-padding;
$o-statusbar-arrow-width: $o-statusbar-height / 3;
$o-statusbar-disabled-bg: lighten($o-brand-lightsecondary, 7%);
-$o-navbar-inverse-link-hover-bg: darken($o-brand-primary, 10%);
+$o-navbar-inverse-link-hover-bg: darken($o-brand-odoo, 10%);
$o-datepicker-week-bg-color: lighten($o-datepicker-week-color, 30%);
diff --git a/addons/web/static/src/scss/tooltip.scss b/addons/web/static/src/scss/tooltip.scss
index 765db1292da..e40852dd6bc 100644
--- a/addons/web/static/src/scss/tooltip.scss
+++ b/addons/web/static/src/scss/tooltip.scss
@@ -9,7 +9,7 @@
max-width: 100vw;
background-color: $o-tooltip-background-color;
color: $o-tooltip-color;
- border-radius: $border-radius-base;
+ border-radius: $border-radius;
box-shadow: 0px 0px 1px 1px $o-brand-secondary;
padding: 5px;
@@ -17,7 +17,7 @@
text-align: left;
.oe_tooltip_string {
- background-color: $o-brand-primary;
+ background-color: $o-brand-odoo;
color: white;
font-weight: bold;
padding: 5px;
diff --git a/addons/web/static/src/scss/ui.scss b/addons/web/static/src/scss/ui.scss
index d88f21f83a1..d8c68853c0a 100644
--- a/addons/web/static/src/scss/ui.scss
+++ b/addons/web/static/src/scss/ui.scss
@@ -13,3 +13,13 @@
[aria-hidden="true"], [aria-hidden="1"] {
display: none!important;
}
+
+.dropdown-toggle {
+ white-space: nowrap;
+
+ &.o-no-caret {
+ &::before, &::after {
+ content: normal;
+ }
+ }
+}
diff --git a/addons/web/static/src/scss/ui_extra.scss b/addons/web/static/src/scss/ui_extra.scss
index 0d97c09092e..e69de29bb2d 100644
--- a/addons/web/static/src/scss/ui_extra.scss
+++ b/addons/web/static/src/scss/ui_extra.scss
@@ -1,10 +0,0 @@
-//------------------------------------------------------------------------------
-// Checkboxes
-//------------------------------------------------------------------------------
-div.o_checkbox {
- display: inline-block;
- vertical-align: sub;
- > input + span {
- display: none;
- }
-}
diff --git a/addons/web/static/src/scss/utils.scss b/addons/web/static/src/scss/utils.scss
index efb8dce7598..9f254c82ecd 100644
--- a/addons/web/static/src/scss/utils.scss
+++ b/addons/web/static/src/scss/utils.scss
@@ -14,119 +14,6 @@
}
// ------------------------------------------------------------------
-// Vendor prefixes
-// ------------------------------------------------------------------
-// Flex
-@mixin o-flex-display {
- display: -ms-flexbox;
- display: -moz-box;
- display: -webkit-box;
- display: -webkit-flex;
-
- display: flex;
-}
-@mixin o-inline-flex-display {
- display: -ms-inline-flexbox;
- display: -moz-inline-box;
- display: -webkit-inline-box;
- display: -webkit-inline-flex;
-
- display: inline-flex;
-}
-@mixin o-flex-flow($direction, $wrap) {
- -ms-flex-flow: $direction $wrap;
- -moz-flex-flow: $direction $wrap;
- -webkit-flex-flow: $direction $wrap;
-
- flex-flow: $direction $wrap;
-}
-@mixin o-flex($grow, $schrink, $basis) {
- -ms-flex: $grow $schrink $basis;
- -moz-flex: $grow $schrink $basis;
- -webkit-box-flex: $grow;
- -webkit-flex: $grow $schrink $basis;
-
- flex: $grow $schrink $basis;
-}
-@mixin o-justify-content($justify) {
- -moz-justify-content: $justify;
- -webkit-justify-content: $justify;
-
- justify-content: $justify;
-}
-@mixin o-align-content($align) {
- -webkit-align-content: $align;
-
- align-content: $align;
-}
-@mixin o-align-items($align) {
- -webkit-align-items: $align;
-
- align-items: $align;
-}
-@mixin o-align-self($align) {
- -webkit-align-self: $align;
-
- align-self: $align;
-}
-
-// Background-size
-@mixin o-background-size($size) {
- -webkit-background-size: $size;
- -moz-background-size: $size;
- -o-background-size: $size;
- background-size: $size;
-}
-
-// ------------------------------------------------------------------
-// Select Appearance
-// ------------------------------------------------------------------
-@mixin o-appearance($value) {
- -webkit-appearance: $value;
- -moz-appearance: $value;
- appearance: $value;
-}
-
-// ------------------------------------------------------------------
-// Transform
-// ------------------------------------------------------------------
-@mixin o-transform-origin($x: 50%, $y: 50%, $z: 0) {
- -ms-transform-origin: $x $y $z;
- -webkit-transform-origin: $x $y $z;
- -moz-transform-origin: $x $y $z;
- transform-origin: $x $y $z;
-}
-
-// ------------------------------------------------------------------
-// Animation
-// ------------------------------------------------------------------
-@mixin o-animation($name: none, $duration: 0s, $timing-function: ease, $delay: 0s, $iteration-count: 1, $direction: normal, $fill-mode: none, $play-state: running) {
- -webkit-animation: $name $duration $timing-function $delay $iteration-count $direction $fill-mode $play-state;
- -moz-animation: $name $duration $timing-function $delay $iteration-count $direction $fill-mode $play-state;
- -o-animation: $name $duration $timing-function $delay $iteration-count $direction $fill-mode $play-state;
- animation: $name $duration $timing-function $delay $iteration-count $direction $fill-mode $play-state;
-}
-
-// ------------------------------------------------------------------
-// Transition
-// ------------------------------------------------------------------
-@mixin o-transition($property: all, $duration: 0s, $timing-function: ease, $transition-delay: 0s) {
- -webkit-transition: $property $duration $timing-function $transition-delay;
- -moz-transition: $property $duration $timing-function $transition-delay;
- -o-transition: $property $duration $timing-function $transition-delay;
- transition: $property $duration $timing-function $transition-delay;
-}
-
-// ------------------------------------------------------------------
-// Columns
-// ------------------------------------------------------------------
-@mixin o-columns($width: auto, $col: auto) {
- -webkit-columns: $width $col;
- -moz-columns: $width $col;
- columns: $width $col;
-}
-
-// ------------------------------------------------------------------
// Position absolute
// ------------------------------------------------------------------
@mixin o-position-absolute($top: auto, $right: auto, $bottom: auto, $left: auto) {
@@ -150,43 +37,6 @@
}
// ------------------------------------------------------------------
-// Gradients
-// ------------------------------------------------------------------
-@mixin o-linear-gradient($deg: 45deg, $start-color: #555, $end-color: #333) {
- background-repeat: repeat-x;
- background-image: -webkit-linear-gradient($deg, $start-color, $end-color);
- background-image: -o-linear-gradient($deg, $start-color, $end-color);
- background-image: linear-gradient($deg, $start-color, $end-color);
-}
-@mixin o-vertical-gradient($startColor: #555, $endColor: #333) {
- background-color: mix($startColor, $endColor);
- background-image: -webkit-gradient(linear, left top, left bottom, from($startColor), to($endColor));
- background-image: -webkit-linear-gradient(top, $startColor, $endColor);
- background-image: -moz-linear-gradient(top, $startColor, $endColor);
- background-image: -ms-linear-gradient(top, $startColor, $endColor);
- background-image: -o-linear-gradient(top, $startColor, $endColor);
- background-image: linear-gradient(to bottom, $startColor, $endColor);
-}
-@mixin o-skew-gradient($startColor: #555, $endColor: #333) {
- background-color: $endColor;
- background: -moz-linear-gradient(135deg, $endColor, $startColor);
- background: -o-linear-gradient(135deg, $startColor, $endColor);
- background: -webkit-gradient(linear, left top, right bottom, from($startColor), to($endColor));
- background: -ms-linear-gradient(top, $startColor, $endColor);
-}
-
-// ------------------------------------------------------------------
-// Transform
-// ------------------------------------------------------------------
-@mixin o-transform($transform) {
- -webkit-transform: $transform;
- -moz-transform: $transform;
- -ms-transform: $transform;
- -o-transform: $transform;
- transform: $transform;
-}
-
-// ------------------------------------------------------------------
// Hovering effects
// ------------------------------------------------------------------
@mixin o-hover-opacity($default-opacity: 0.5, $hover-opacity: 1) {
@@ -222,7 +72,7 @@
// ------------------------------------------------------------------
// Caret
// ------------------------------------------------------------------
-@mixin o-caret-down($caret-width: $caret-width-base) {
+@mixin o-caret-down($caret-width: $caret-width) {
@include utils-caret-boilerplate;
border-bottom: 0;
border-left: $caret-width solid transparent;
@@ -230,7 +80,7 @@
border-top: $caret-width solid;
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
-@mixin o-caret-up($caret-width: $caret-width-base) {
+@mixin o-caret-up($caret-width: $caret-width) {
@include utils-caret-boilerplate;
border-bottom: $caret-width solid;
border-left: $caret-width solid transparent;
@@ -238,7 +88,7 @@
border-top: 0;
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
-@mixin o-caret-left($caret-width: $caret-width-base) {
+@mixin o-caret-left($caret-width: $caret-width) {
@include utils-caret-boilerplate;
border-bottom: $caret-width solid transparent;
border-left: 0;
@@ -246,7 +96,7 @@
border-top: $caret-width solid transparent;
-moz-transform: scale(0.9999); // Smooth the caret on firefox
}
-@mixin o-caret-right($caret-width: $caret-width-base) {
+@mixin o-caret-right($caret-width: $caret-width) {
@include utils-caret-boilerplate;
border-bottom: $caret-width solid transparent;
border-left: $caret-width solid;
@@ -258,25 +108,22 @@
// ------------------------------------------------------------------
// Dropdowns
// ------------------------------------------------------------------
-@mixin o-selected-li {
- li {
+@mixin o-selected-li { // FIXME use active ?
+ .dropdown-item {
position: relative;
- > a {
- color: $o-main-text-color;
- &:hover {
- color: darken($o-main-text-color, 10%);
- }
+ color: $o-main-text-color;
+ &:hover {
+ color: darken($o-main-text-color, 10%);
}
+
&.selected {
- > a {
- color: darken($o-main-text-color, 10%);
- font-weight: bold;
- &:before {
- font-family: FontAwesome;
- position: absolute;
- left: 6px;
- content: "\f00c";
- }
+ color: darken($o-main-text-color, 10%);
+ font-weight: bold;
+ &:before {
+ font-family: FontAwesome;
+ position: absolute;
+ left: 6px;
+ content: "\f00c";
}
}
}
@@ -285,7 +132,7 @@
// ------------------------------------------------------------------
// Hovering effects
// ------------------------------------------------------------------
-@mixin o-hover-text-color($default-color: $text-color, $hover-color: $link-color) {
+@mixin o-hover-text-color($default-color: $body-color, $hover-color: $link-color) {
color: $default-color;
&:hover, &:focus, &.focus {
@@ -316,7 +163,7 @@
display: block;
text-align: center;
color: $o-main-text-color;
- font-size: $font-size-small;
+ font-size: $font-size-sm;
cursor: pointer;
@include o-hover-opacity($base-opacity);
}
@@ -339,22 +186,22 @@
}
@mixin o-kanban-slim-col {
position: relative;
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
margin: 0;
padding: 0 floor($o-kanban-group-padding * 0.7);
cursor: pointer;
}
@mixin o-kanban-header-title {
- @include o-flex-display;
- @include o-align-items(center);
+ display: flex;
+ align-items: center;
height: $o-kanban-header-title-height;
line-height: 2.2;
color: $headings-color;
}
@mixin o-kanban-v-title {
@include o-position-absolute($o-kanban-inside-vgutter * 2, $left: floor(-$o-kanban-inside-vgutter * 1.2));
- @include o-transform-origin(left, bottom, $z: 0);
- @include o-transform(rotate(90deg));
+ transform-origin: left bottom 0;
+ transform: rotate(90deg);
overflow: visible;
white-space: nowrap;
font-size: 15px;
@@ -374,7 +221,7 @@
border: 1px solid transparent;
border-bottom: none;
vertical-align: top;
- color: $text-color;
+ color: $body-color;
&:hover {
color: $headings-color;
@@ -386,13 +233,13 @@
@mixin o-kanban-dropdown-open {
position: relative;
background: white;
- border-color: $gray-lighter-darker;
+ border-color: gray('400');
z-index: $zindex-dropdown + 1;
}
@mixin o-kanban-dropdown-menu {
@include o-position-absolute($right: -1px);
margin-top: -1px;
- border-color: $gray-lighter-darker;
+ border-color: gray('400');
}
@mixin o-kanban-colorpicker {
max-width: 150px;
@@ -402,7 +249,7 @@
display: inline-block;
margin: $o-kanban-inner-hmargin $o-kanban-inner-hmargin 0 0;
border: 1px solid white;
- box-shadow: 0 0 0 1px $gray-lighter-dark;
+ box-shadow: 0 0 0 1px gray('300');
> a {
display: block;
@@ -424,7 +271,7 @@
display: block;
width: 1px;
height: 20px;
- @include rotate(45deg);
+ transform: rotate(45deg);
background-color: red;
}
&::after {
@@ -441,11 +288,11 @@
> a {
margin: auto auto auto (-$link-padding-gap);
padding: 3px $link-padding-gap;
- color: $text-color;
+ color: $body-color;
display: block;
&:hover {
- background-color: $gray-lighter-dark;
+ background-color: gray('300');
color: $headings-color;
}
}
diff --git a/addons/web/static/src/scss/views.scss b/addons/web/static/src/scss/views.scss
index e3562026ffe..e4e86231940 100644
--- a/addons/web/static/src/scss/views.scss
+++ b/addons/web/static/src/scss/views.scss
@@ -18,13 +18,13 @@
border-radius: 6px;
vertical-align: middle;
- background-color: $gray-lighter-dark;
+ background-color: gray('300');
&.o_status_green {
- background-color: $brand-success;
+ background-color: theme-color('success');
}
&.o_status_red {
- background-color: $brand-danger;
+ background-color: theme-color('danger');
}
}
diff --git a/addons/web/static/src/scss/web_calendar.scss b/addons/web/static/src/scss/web_calendar.scss
index 7091cbc3c98..ae22efb2675 100644
--- a/addons/web/static/src/scss/web_calendar.scss
+++ b/addons/web/static/src/scss/web_calendar.scss
@@ -1,12 +1,12 @@
@keyframes backgroundfade {
- from {background-color: rgba($o-brand-primary, 0.5);}
+ from {background-color: rgba($o-brand-odoo, 0.5);}
to {background-color: #f5f5f5;}
}
.o_calendar_container {
height: 100%;
@include o-webclient-padding($top: $o-horizontal-padding/2, $bottom: $o-horizontal-padding/2);
- @include o-flex-display;
+ display: flex;
@for $index from 1 through $o-nb-calendar-colors {
.o_calendar_color_#{$index} {
@@ -28,7 +28,7 @@
}
.o_calendar_view {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
min-width: 0;
.o_calendar_widget {
@@ -62,7 +62,7 @@
}
.o_calendar_sidebar_container {
- @include o-flex(0, 0, $o-horizontal-padding);
+ flex: 0 0 $o-horizontal-padding;
position: relative;
&.o_sidebar_hidden {
@@ -97,13 +97,13 @@
padding: 0;
.ui-widget-header {
- @include o-flex-display;
+ display: flex;
background: none;
background-color: lighten($o-brand-secondary, 30%);
border-radius: 0;
.ui-datepicker-prev, .ui-datepicker-next {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
position: static;
cursor: pointer;
padding: 2px;
@@ -133,7 +133,7 @@
}
}
.ui-datepicker-title {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
order: 2;
display: inline-block;
margin: 0 10px;
@@ -151,22 +151,22 @@
}
}
.ui-state-default {
- color: $o-brand-primary;
+ color: $o-brand-odoo;
&:hover {
background: none;
- background-color: rgba($o-brand-primary, 0.5);
- border-color: $o-brand-primary;
+ background-color: rgba($o-brand-odoo, 0.5);
+ border-color: $o-brand-odoo;
color: $o-view-background-color;
};
}
.ui-state-active {
background: none;
- background-color: $o-brand-primary;
+ background-color: $o-brand-odoo;
color: $o-view-background-color;
}
.o_selected_range.o_color {
background: none;
- background-color: $o-brand-primary;
+ background-color: $o-brand-odoo;
animation: backgroundfade 3s forwards;
}
}
@@ -199,12 +199,12 @@
}
// Mobile rules
-@media only screen and (max-width: 768px) {
+@include media-breakpoint-down(sm) {
.o_calendar_container {
padding: 0;
}
}
-@media (max-width: $screen-xs-max) {
+@include media-breakpoint-down(sm) {
.o_control_panel {
.o_calendar_button_today {
float: right;
diff --git a/addons/web/static/src/scss/webclient.scss b/addons/web/static/src/scss/webclient.scss
index 8f4dadb22df..8c213a57682 100644
--- a/addons/web/static/src/scss/webclient.scss
+++ b/addons/web/static/src/scss/webclient.scss
@@ -1,3 +1,7 @@
+:root {
+ font-size: $o-root-font-size;
+}
+
// ------------------------------------------------------------------
// General
// ------------------------------------------------------------------
@@ -13,7 +17,7 @@
width: 300px;
max-width: 100%;
- @include o-position-absolute($navbar-height, 0px);
+ @include o-position-absolute($nav-link-height, 0);
z-index: 1100; // Bootstrap modal z-index is 1050
.o_notification {
@@ -33,8 +37,8 @@
}
.o_notification_title {
- @include o-flex-display;
- @include o-align-items(center);
+ display: flex;
+ align-items: center;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
padding: 10px 10px 10px 20px;
@@ -101,26 +105,26 @@ div.o_boolean_toggle {
}
> input:checked + .slider {
- background-color: $o-brand-optional;
+ background-color: $o-brand-primary;
&:before {
- @include translate(14px, 0px);
+ transform: translate(14px, 0px);
}
}
}
// Full bg colors (bootstrap extension)
.bg-success-full {
- background-color: $brand-success;
+ background-color: theme-color('success');
}
.bg-warning-full {
- background-color: $brand-warning;
+ background-color: theme-color('warning');
}
.bg-danger-full {
- background-color: $brand-danger;
+ background-color: theme-color('danger');
}
.bg-info-full {
- background-color: $brand-info;
+ background-color: theme-color('info');
}
.o_web_accesskey_overlay {
@@ -151,28 +155,26 @@ div.o_boolean_toggle {
//== Badges
.badge {
margin: 1px 2px 1px 0;
- padding-top: 0;
- padding-bottom: 0;
}
// Btn-link variations
.btn-link {
font-weight: $btn-font-weight;
- &.btn-default {
- @include o-btn-link-variant($text-color, $headings-color);
+ &.btn-secondary {
+ @include o-btn-link-variant($body-color, $headings-color);
}
&.btn-success, &.text-success {
- @include o-btn-link-variant($text-color, $brand-success);
+ @include o-btn-link-variant($body-color, theme-color('success'));
}
&.btn-warning, &.text-warning {
- @include o-btn-link-variant($text-color, $brand-warning);
+ @include o-btn-link-variant($body-color, theme-color('warning'));
}
&.btn-danger, &.text-danger {
- @include o-btn-link-variant($text-color, $brand-danger);
+ @include o-btn-link-variant($body-color, theme-color('danger'));
}
&.btn-info, &.text-info {
- @include o-btn-link-variant($text-color, darken($brand-info, 20%));
+ @include o-btn-link-variant($body-color, darken(theme-color('info'), 20%));
}
}
diff --git a/addons/web/static/src/scss/webclient_extra.scss b/addons/web/static/src/scss/webclient_extra.scss
index cc87e526f8d..80e9390c534 100644
--- a/addons/web/static/src/scss/webclient_extra.scss
+++ b/addons/web/static/src/scss/webclient_extra.scss
@@ -8,7 +8,7 @@
}
.o_input {
border: 1px solid $o-form-lightsecondary;
- border-radius: $border-radius-base;
+ border-radius: $border-radius;
padding: 2px 4px;
color: #1f1f1f;
@@ -29,7 +29,7 @@ select {
top: 0;
right: 50%;
padding: 4px 12px;
- background-color: $o-color-pink;
+ background-color: $o-enterprise-color; // FIXME probably supposed to be primary to be auto-adapted in enterprise ?
color: white;
text-align: center;
border-top: none;
@@ -44,8 +44,3 @@ select {
@include o-text-overflow;
max-width: 150px;
}
-
-// Button
-.btn-icon {
- @include button-variant($btn-default-color, $btn-default-bg, $btn-default-border);
-}
diff --git a/addons/web/static/src/scss/webclient_layout.scss b/addons/web/static/src/scss/webclient_layout.scss
index f811df48802..c8bb9e3c3ed 100644
--- a/addons/web/static/src/scss/webclient_layout.scss
+++ b/addons/web/static/src/scss/webclient_layout.scss
@@ -1,7 +1,7 @@
.o_web_client {
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
+ display: flex;
+ flex-flow: column nowrap;
overflow: hidden;
&.o_fullscreen {
@@ -15,7 +15,7 @@
.navbar {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
li > a {
padding: 4px 8px;
@@ -30,20 +30,20 @@
}
> .o_main {
- @include o-flex(1, 1, auto);
- @include o-flex-display;
+ flex: 1 1 auto;
+ display: flex;
min-height: 0; // Allow flex to shrink this element as much as it wants
height: 100%;
.o_sub_menu {
- @include o-flex(0, 0, 220px);
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
+ flex: 0 0 220px;
+ display: flex;
+ flex-flow: column nowrap;
border-right: 1px solid darken($o-control-panel-background-color, 20%);
background-color: $o-control-panel-background-color;
.o_sub_menu_logo {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
text-align: center;
position: relative;
@@ -67,14 +67,14 @@
}
.o_sub_menu_content {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
height:100%;
overflow-y: auto;
.oe_secondary_menu_section {
font-weight: bold;
margin-left: 8px;
- color: $o-brand-optional;
+ color: $o-brand-primary;
}
.oe_secondary_submenu {
margin: 3px 0px 10px;
@@ -128,28 +128,28 @@
}
.o_sub_menu_footer {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
text-align: center;
> a {
font-weight: bold;
> span {
- color: $o-color-pink;
+ color: $o-enterprise-color; // FIXME probably supposed to be primary to be auto-adapted in enterprise ?
}
}
}
}
.o_main_content {
- @include o-flex(1, 1, auto);
- @include o-flex-display;
- @include o-flex-flow(column, nowrap);
+ flex: 1 1 auto;
+ display: flex;
+ flex-flow: column nowrap;
.o_control_panel {
- @include o-flex(0, 0, auto);
+ flex: 0 0 auto;
}
.o_content {
- @include o-flex(1, 1, auto);
+ flex: 1 1 auto;
height: 100%;
overflow: auto;
position: relative;
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index b92c143dc5f..a30ed34c264 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -123,7 +123,7 @@
</div>
<div class="o_notification_content" t-if="widget.message"><t t-raw="widget.message"/></div>
<div t-if="widget.buttons.length" class="o_buttons">
- <button t-foreach="widget.buttons" t-as="button" t-attf-class="btn btn-sm #{button.primary ? 'btn-primary' : 'btn-default'}" type="button">
+ <button t-foreach="widget.buttons" t-as="button" t-attf-class="btn #{button.primary ? 'btn-primary' : 'btn-secondary'}" type="button">
<t t-if="button.icon">
<i t-if="button.icon.indexOf('fa-') === 0" t-attf-class="fa fa-fw o_button_icon #{button.icon}" role="img" t-att-aria-label="button.name" t-att-title="button.name"/>
<img t-else="" t-att-src="button.icon" t-att-alt="button.name"/>
@@ -143,7 +143,7 @@
</div>
<div t-name="CrashManager.error" class="o_dialog_error">
<div class="alert alert-warning clearfix" role="alert">
- <button class="btn btn-sm btn-primary pull-right ml8 o_clipboard_button">
+ <button class="btn btn-primary float-right ml8 o_clipboard_button">
<i class="fa fa-clipboard mr8"/>Copy the full error to clipboard
</button>
<p><b>An error occurred</b></p>
@@ -151,7 +151,7 @@
</div>
<t t-set="errUID" t-value="_.uniqueId()"/>
- <button class="btn btn-sm btn-link" t-att-data-target="'#o_error_detail' + errUID" data-toggle="collapse">See details</button>
+ <button class="btn btn-link" t-att-data-target="'#o_error_detail' + errUID" data-toggle="collapse">See details</button>
<div t-att-id="'o_error_detail' + errUID" class="collapse alert alert-danger o_error_detail" role="alert">
<pre><t t-esc="error.message"/></pre>
<pre><t t-esc="error.data.debug"/></pre>
@@ -175,8 +175,8 @@
</tr>
</table>
- <button type="button" class="btn btn-sm btn-primary oe_form_button">Change Password</button>
- <button type="button" class="btn btn-sm btn-default oe_form_button oe_form_button_cancel" href="javascript:void(0)">Cancel</button>
+ <button type="button" class="btn btn-primary oe_form_button">Change Password</button>
+ <button type="button" class="btn btn-secondary oe_form_button oe_form_button_cancel" href="javascript:void(0)">Cancel</button>
</div>
</form>
@@ -191,7 +191,7 @@
<div class="o_cp_right">
<div class="btn-group o_search_options" role="search"/>
<nav class="o_cp_pager" role="search" aria-label="Pager"/>
- <nav class="btn-group btn-group-sm o_cp_switch_buttons" role="toolbar" aria-label="View switcher"/>
+ <nav class="btn-group o_cp_switch_buttons" role="toolbar" aria-label="View switcher"/>
</div>
</div>
</t>
@@ -204,7 +204,7 @@
<t t-name="ControlPanel.SwitchButton">
<button type="button" t-att-accesskey="view.accessKey"
- t-attf-class="btn btn-icon fa fa-lg #{view.icon} o_cp_switch_#{view.type}"
+ t-attf-class="btn btn-secondary fa fa-lg #{view.icon} o_cp_switch_#{view.type}"
t-attf-aria-label="View #{view.type}"
t-att-data-view-type="view.type" t-attf-title="View #{view.type}" tabindex="-1"/>
</t>
@@ -231,31 +231,31 @@
<a href="#" title="Open Developer Tools" aria-label="Open Developer Tools" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" tabindex="-1">
<span class="fa fa-bug"/>
</a>
- <ul class="dropdown-menu o_debug_dropdown" role="menu"/>
+ <div class="dropdown-menu dropdown-menu-right o_debug_dropdown" role="menu"/>
</li>
</t>
<t t-name="WebClient.DebugManager.Global">
- <li><a role="menuitem" href="#" data-action="perform_js_tests">Run JS Tests</a></li>
- <li><a role="menuitem" href="#" data-action="perform_js_mobile_tests">Run JS Mobile Tests</a></li>
- <li><a role="menuitem" href="#" data-action="select_view">Open View</a></li>
+ <a role="menuitem" href="#" data-action="perform_js_tests" class="dropdown-item">Run JS Tests</a>
+ <a role="menuitem" href="#" data-action="perform_js_mobile_tests" class="dropdown-item">Run JS Mobile Tests</a>
+ <a role="menuitem" href="#" data-action="select_view" class="dropdown-item">Open View</a>
<t t-if="manager._events">
- <li class="divider" role="separator"/>
- <li><a role="menuitem" href="#" data-action="show_timelines">Toggle Timelines</a></li>
- <li><a role="menuitem" href="#" data-action="requests_clear">Clear Events</a></li>
+ <div class="dropdown-divider" role="separator"/>
+ <a role="menuitem" href="#" data-action="show_timelines" class="dropdown-item">Toggle Timelines</a>
+ <a role="menuitem" href="#" data-action="requests_clear" class="dropdown-item">Clear Events</a>
</t>
- <li class="divider o_debug_leave_section" role="separator"/>
- <li><a role="menuitem" href="#" data-action="split_assets">Activate Assets Debugging</a></li>
- <li><a role="menuitem" href="#" data-action="regenerateAssets">Regenerate Assets Bundles</a></li>
- <li><a role="menuitem" href="#" data-action="leave_debug_mode">Leave the Developer Tools</a></li>
+ <div class="dropdown-divider o_debug_leave_section" role="separator"/>
+ <a role="menuitem" href="#" data-action="split_assets" class="dropdown-item">Activate Assets Debugging</a>
+ <a role="menuitem" href="#" data-action="regenerateAssets" class="dropdown-item">Regenerate Assets Bundles</a>
+ <a role="menuitem" href="#" data-action="leave_debug_mode" class="dropdown-item">Leave the Developer Tools</a>
</t>
<t t-name="WebClient.DebugManager.Action">
<t t-if="action">
- <li class="divider" role="separator"/>
- <li><a role="menuitem" href="#" data-action="edit" t-att-data-model="action.type" t-att-data-id="action.id">Edit Action</a></li>
+ <div class="dropdown-divider" role="separator"/>
+ <a role="menuitem" href="#" data-action="edit" t-att-data-model="action.type" t-att-data-id="action.id" class="dropdown-item">Edit Action</a>
<t t-if="action.res_model">
- <li><a role="menuitem" href="#" data-action="get_view_fields">View Fields</a></li>
- <li><a role="menuitem" href="#" data-action="manage_filters">Manage Filters</a></li>
- <li><a role="menuitem" href="#" data-action="translate">Technical Translation</a></li>
+ <a role="menuitem" href="#" data-action="get_view_fields" class="dropdown-item">View Fields</a>
+ <a role="menuitem" href="#" data-action="manage_filters" class="dropdown-item">Manage Filters</a>
+ <a role="menuitem" href="#" data-action="translate" class="dropdown-item">Technical Translation</a>
</t>
</t>
</t>
@@ -272,26 +272,24 @@
</t>
<t t-name="WebClient.DebugManager.View">
<t t-if="view">
- <li role="separator" class="divider"/>
+ <div role="separator" class="dropdown-divider"/>
<t t-if="view.type === 'form'">
- <li><a role="menuitem" href="#" data-action="set_defaults">Set Defaults</a></li>
+ <a role="menuitem" href="#" data-action="set_defaults" class="dropdown-item">Set Defaults</a>
<t t-if="controller.getSelectedIds().length === 1">
- <li><a role="menuitem" href="#" data-action="get_metadata">View Metadata</a></li>
+ <a role="menuitem" href="#" data-action="get_metadata" class="dropdown-item">View Metadata</a>
</t>
</t>
- <li><a role="menuitem" href="#" data-action="fvg">Fields View Get</a></li>
+ <a role="menuitem" href="#" data-action="fvg" class="dropdown-item">Fields View Get</a>
<t t-if="can_edit">
- <li>
- <a role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="view.fieldsView.view_id">
+ <a role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="view.fieldsView.view_id" class="dropdown-item">
Edit View: <t t-esc="_.str.capitalize(view.type)"/>
- </a>
- </li>
- <li t-if="searchview and searchview.$el.is(':visible')"><a role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="action.searchFieldsView.view_id">Edit SearchView</a></li>
+ </a>
+ <a t-if="searchview and searchview.$el.is(':visible')" role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="action.searchFieldsView.view_id" class="dropdown-item">Edit SearchView</a>
</t>
</t>
</t>
<t t-name="WebClient.DebugViewLog">
- <table class="table table-condensed table-striped">
+ <table class="table table-sm table-striped">
<tr>
<th>ID:</th>
<td><t t-esc="perm.id"/></td>
@@ -342,17 +340,17 @@
<t t-name="Sidebar">
<t t-foreach="widget.sections" t-as="section">
<div class="btn-group o_dropdown">
- <button t-if="section.name != 'buttons'" class="o_dropdown_toggler_btn btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
+ <button t-if="section.name != 'buttons'" class="o_dropdown_toggler_btn btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<t t-if="section.name == 'files'" t-raw="widget.items[section.name].length || ''"/>
- <t t-esc="section.label"/> <span class="caret"/>
+ <t t-esc="section.label"/>
</button>
<t t-if="section.name == 'buttons'" t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
<a t-att-title="item.title or None" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url or '#'" target="_blank">
<t t-raw="item.label"/>
</a>
</t>
- <ul class="dropdown-menu" role="menu">
- <li role="menuitem" t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
+ <div class="dropdown-menu" role="menu">
+ <t t-foreach="widget.items[section.name]" t-as="item">
<t t-if="section.name == 'files'">
<t t-set="item.title">
<b>Attachment : </b><br/>
@@ -369,12 +367,12 @@
<t t-raw="item.write_uid[1]"/> <t t-esc="item.write_date_string"/>
</t>
</t>
- <a t-att-title="item.title or None" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url or '#'">
+ <a t-attf-class="dropdown-item #{item.classname}" role="menuitem" t-att-title="item.title or None" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url or '#'">
<t t-raw="item.label"/>
<span t-if="section.name == 'files' and widget.options.editable and !item.callback" class="fa fa-trash-o o_sidebar_delete_attachment" t-att-data-id="item.id" title="Delete this attachment" role="img" aria-label="Delete this attachment"/>
</a>
- </li>
- <li role="menuitem" t-if="section.name == 'files' and widget.options.editable" class="o_sidebar_add_attachment">
+ </t>
+ <div role="menuitem" t-if="section.name == 'files' and widget.options.editable" class="dropdown-item o_sidebar_add_attachment">
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileuploadId"/>
<t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
@@ -384,8 +382,8 @@
<input type="hidden" name="session_id" t-att-value="widget.getSession().session_id" t-if="widget.getSession().override_session"/>
<span>Add...</span>
</t>
- </li>
- </ul>
+ </div>
+ </div>
</div>
</t>
</t>
@@ -393,14 +391,14 @@
<t t-name="ListView.buttons">
<div class="o_list_buttons" role="toolbar" aria-label="Main actions">
<t t-if="widget.is_action_enabled('create')">
- <button type="button" class="btn btn-primary btn-sm o_list_button_add" accesskey="c">
+ <button type="button" class="btn btn-primary o_list_button_add" accesskey="c">
Create
</button>
</t>
- <button type="button" class="btn btn-primary btn-sm o_list_button_save" accesskey="s">
+ <button type="button" class="btn btn-primary o_list_button_save" accesskey="s">
Save
</button>
- <button type="button" class="btn btn-default btn-sm o_list_button_discard" accesskey="j">
+ <button type="button" class="btn btn-secondary o_list_button_discard" accesskey="j">
Discard
</button>
</div>
@@ -409,21 +407,21 @@
<t t-name="FormView.buttons">
<div class="o_form_buttons_view" role="toolbar" aria-label="Main actions">
<button t-if="widget.is_action_enabled('edit')" type="button"
- class="btn btn-primary btn-sm o_form_button_edit" accesskey="a">
+ class="btn btn-primary o_form_button_edit" accesskey="a">
Edit
</button>
<button t-if="widget.is_action_enabled('create')" type="button"
- class="btn btn-default btn-sm o_form_button_create" accesskey="c">
+ class="btn btn-secondary o_form_button_create" accesskey="c">
Create
</button>
</div>
<div class="o_form_buttons_edit" role="toolbar" aria-label="Main actions">
<button type="button"
- class="btn btn-primary btn-sm o_form_button_save" accesskey="s">
+ class="btn btn-primary o_form_button_save" accesskey="s">
Save
</button>
<button type="button"
- class="btn btn-default btn-sm o_form_button_cancel" accesskey="j">
+ class="btn btn-secondary o_form_button_cancel" accesskey="j">
Discard
</button>
</div>
@@ -447,7 +445,7 @@
<t t-name="FormButton.tooltip">
<div class="oe_tooltip_string" role="tooltip">
<div class="tooltip-inner">
- Hit ENTER to
+ Hit ENTER to
<t t-esc="title"></t>
</div>
</div>
@@ -509,22 +507,22 @@
</table>
</form>
<t t-name="GraphView.buttons">
- <div class="btn-group btn-group-sm" role="toolbar" aria-label="Main actions">
- <button class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
- Measures <span class="caret"/>
+ <div class="btn-group" role="toolbar" aria-label="Main actions">
+ <button class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
+ Measures
</button>
- <ul class="dropdown-menu o_graph_measures_list" role="menu">
- <li t-foreach="measures" t-as="measure" t-att-data-field="measure[0]">
- <a role="menuitem" href="#"><t t-esc="measure[1].string"/><t t-if="measure[1].type === 'many2one'"> (count)</t></a>
- </li>
- <li role="separator" class="divider"></li>
- <li data-field="__count__"><a role="menuitem" href="#">Count</a></li>
- </ul>
+ <div class="dropdown-menu o_graph_measures_list" role="menu">
+ <t t-foreach="measures" t-as="measure">
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-field="measure[0]"><t t-esc="measure[1].string"/><t t-if="measure[1].type === 'many2one'"> (count)</t></a>
+ </t>
+ <div role="separator" class="dropdown-divider"/>
+ <a role="menuitem" href="#" class="dropdown-item" data-field="__count__">Count</a>
+ </div>
</div>
- <div class="btn-group btn-group-sm" role="toolbar" aria-label="Change graph">
- <button class="btn btn-default fa fa-bar-chart-o o_graph_button" title="Bar Chart" aria-label="Bar Chart" data-mode="bar"/>
- <button class="btn btn-default fa fa-line-chart o_graph_button" title="Line Chart" aria-label="Line Chart" data-mode="line"/>
- <button class="btn btn-default fa fa-pie-chart o_graph_button" title="Pie Chart" aria-label="Pie Chart" data-mode="pie"/>
+ <div class="btn-group" role="toolbar" aria-label="Change graph">
+ <button class="btn btn-secondary fa fa-bar-chart-o o_graph_button" title="Bar Chart" aria-label="Bar Chart" data-mode="bar"/>
+ <button class="btn btn-secondary fa fa-line-chart o_graph_button" title="Line Chart" aria-label="Line Chart" data-mode="line"/>
+ <button class="btn btn-secondary fa fa-pie-chart o_graph_button" title="Pie Chart" aria-label="Pie Chart" data-mode="pie"/>
</div>
</t>
<div t-name="GraphView.error" class="o_view_nocontent" role="alert">
@@ -538,48 +536,46 @@
<div class="o_field_selection"/>
</div>
<t t-name="PivotView.buttons">
- <div class="btn-group btn-group-sm" role="toolbar" aria-label="Main actions">
- <button class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
- Measures <span class="caret"/>
+ <div class="btn-group" role="toolbar" aria-label="Main actions">
+ <button class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
+ Measures
</button>
- <ul class="dropdown-menu o_pivot_measures_list" role="menu">
- <li t-foreach="measures" t-as="measure" t-att-data-field="measure[0]">
- <a role="menuitem" href="#"><t t-esc="measure[1].string"/><t t-if="measure[1].type === 'many2one'"> (count)</t></a>
- </li>
- <li role="separator" class="divider"></li>
- <li data-field="__count"><a role="menuitem" href="#">Count</a></li>
- </ul>
+ <div class="dropdown-menu o_pivot_measures_list" role="menu">
+ <t t-foreach="measures" t-as="measure">
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-field="measure[0]"><t t-esc="measure[1].string"/><t t-if="measure[1].type === 'many2one'"> (count)</t></a>
+ </t>
+ <div role="separator" class="dropdown-divider"/>
+ <a role="menuitem" href="#" class="dropdown-item" data-field="__count">Count</a>
+ </div>
</div>
- <div class="btn-group btn-group-sm" role="toolbar" aria-label="Pivot settings">
- <button class="btn btn-default fa fa-expand o_pivot_flip_button" title="Flip axis" aria-label="Flip axis"/>
- <button class="btn btn-default fa fa-arrows-alt o_pivot_expand_button" title="Expand all" aria-label="Expand all"/>
- <button class="btn btn-default fa fa-download o_pivot_download" title="Download xls" aria-label="Download xls"/>
+ <div class="btn-group" role="toolbar" aria-label="Pivot settings">
+ <button class="btn btn-secondary fa fa-expand o_pivot_flip_button" title="Flip axis" aria-label="Flip axis"/>
+ <button class="btn btn-secondary fa fa-arrows-alt o_pivot_expand_button" title="Expand all" aria-label="Expand all"/>
+ <button class="btn btn-secondary fa fa-download o_pivot_download" title="Download xls" aria-label="Download xls"/>
</div>
</t>
<t t-name="PivotView.FieldSelection">
- <ul class="dropdown-menu o_pivot_field_menu" role="menu">
+ <div class="dropdown-menu o_pivot_field_menu" role="menu">
<t t-foreach="fields" t-as="field">
<t t-if="(field[1].type === 'date') || (field[1].type === 'datetime')">
- <li role="menuitem" aria-haspopup="true" t-att-data-field="field[0]" t-attf-class="o_inline_dropdown#{field[2] ? ' disabled' : ''}">
- <a href="#" class="o_pivot_field_selection">
+ <div role="menuitem" aria-haspopup="true" class="o_inline_dropdown">
+ <a href="#" t-att-data-field="field[0]" t-attf-class="dropdown-item o_pivot_field_selection#{field[2] ? ' disabled' : ''}">
<t t-esc="field[1].string"/>
</a>
- <ul class="dropdown-menu" role="menu">
- <li t-att-data-field="field[0]"><a role="menuitem" href="#" t-att-data-interval="'day'">Day</a></li>
- <li t-att-data-field="field[0]"><a role="menuitem" href="#" t-att-data-interval="'week'">Week</a></li>
- <li t-att-data-field="field[0]"><a role="menuitem" href="#" t-att-data-interval="'month'">Month</a></li>
- <li t-att-data-field="field[0]"><a role="menuitem" href="#" t-att-data-interval="'quarter'">Quarter</a></li>
- <li t-att-data-field="field[0]"><a role="menuitem" href="#" t-att-data-interval="'year'">Year</a></li>
- </ul>
- </li>
+ <div class="dropdown-menu" role="menu">
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-interval="'day'" t-att-data-field="field[0]">Day</a>
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-interval="'week'" t-att-data-field="field[0]">Week</a>
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-interval="'month'" t-att-data-field="field[0]">Month</a>
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-interval="'quarter'" t-att-data-field="field[0]">Quarter</a>
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-interval="'year'" t-att-data-field="field[0]">Year</a>
+ </div>
+ </div>
</t>
<t t-else="">
- <li t-att-data-field="field[0]" t-att-class="(field[2] ? 'disabled' : '')">
- <a role="menuitem" href="#"><t t-esc="field[1].string"/></a>
- </li>
+ <a href="#" role="menuitem" t-att-data-field="field[0]" t-attf-class="dropdown-item#{field[2] ? ' disabled' : ''}"><t t-esc="field[1].string"/></a>
</t>
</t>
- </ul>
+ </div>
</t>
<div t-name="PivotView.nodata">
<div class="o_view_nocontent" role="alert">
@@ -597,28 +593,27 @@
<t t-name="FormSelection">
<div class="btn-group o_selection" aria-atomic="true">
<a href="#" data-toggle="dropdown" aria-label="Dropdown menu" title="Dropdown menu"><span class="o_status"/></a>
- <ul class="dropdown-menu state" role="menu">
- </ul>
+ <div class="dropdown-menu state" role="menu"/>
</div>
</t>
<t t-name="FormSelection.items">
- <li t-foreach="states" t-as="rec" t-att-data-value="rec.name">
- <a role="menuitem" href="#">
+ <t t-foreach="states" t-as="rec">
+ <a role="menuitem" href="#" class="dropdown-item" t-att-data-value="rec.name">
<span t-att-class="'o_status ' + (rec.state_class &amp;&amp; rec.state_class || '')"/>
<t t-raw="rec.state_name"/>
</a>
- </li>
+ </t>
</t>
<t t-name="FieldDomain.content">
<div t-if="hasModel" class="o_field_domain_panel">
<i class="fa fa-arrow-right" role="img" aria-label="Domain" title="Domain"/>
- <button t-if="isValid" class="btn btn-xs btn-default o_domain_show_selection_button" type="button">
+ <button t-if="isValid" class="btn btn-sm btn-secondary o_domain_show_selection_button" type="button">
<t t-esc="nbRecords"/> record(s)
</button>
<span t-else="" class="text-warning" role="alert"><i class="fa fa-exclamation-triangle" role="img" aria-label="Warning" title="Warning"/> Invalid domain</span>
- <button t-if="inDialogEdit" class="btn btn-xs btn-primary o_field_domain_dialog_button">Edit Domain</button>
+ <button t-if="inDialogEdit" class="btn btn-sm btn-primary o_field_domain_dialog_button">Edit Domain</button>
</div>
<div t-else="">Select a model to add a filter.</div>
</t>
@@ -631,15 +626,15 @@
</t>
<t t-name="DomainTree.OperatorSelector">
<div t-if="!widget.readonly" class="btn-group o_domain_tree_operator_selector" aria-atomic="true">
- <button class="btn btn-xs btn-primary o_domain_tree_operator_caret" data-toggle="dropdown">
+ <button class="btn btn-sm btn-primary o_domain_tree_operator_caret" data-toggle="dropdown">
<t t-if="widget.operator === '&amp;'">All</t>
<t t-if="widget.operator === '|'">Any</t>
<t t-if="widget.operator === '!'">None</t>
</button>
- <ul class="dropdown-menu" role="menu">
- <li><a role="menuitem" href="#" data-operator="&amp;">All</a></li>
- <li><a role="menuitem" href="#" data-operator="|">Any</a></li>
- </ul>
+ <div class="dropdown-menu" role="menu">
+ <a role="menuitem" href="#" class="dropdown-item" data-operator="&amp;">All</a>
+ <a role="menuitem" href="#" class="dropdown-item" data-operator="|">Any</a>
+ </div>
</div>
<strong t-else="">
<t t-if="widget.operator === '&amp;'">ALL</t>
@@ -650,7 +645,7 @@
<div aria-atomic="true" t-name="DomainSelector" t-attf-class="o_domain_node o_domain_tree o_domain_selector #{widget.readonly ? 'o_read_mode' : 'o_edit_mode'}">
<t t-if="widget.children.length === 0">
<span>Match <strong>all records</strong></span>
- <button t-if="!widget.readonly" class="btn btn-xs btn-primary o_domain_add_first_node_button"><i class="fa fa-plus"/> Add filter</button>
+ <button t-if="!widget.readonly" class="btn btn-sm btn-primary o_domain_add_first_node_button"><i class="fa fa-plus"/> Add filter</button>
</t>
<t t-else="">
<div class="o_domain_tree_header">
@@ -692,7 +687,7 @@
</option>
</select>
</div>
- <div t-attf-class="o_ds_value_cell#{_.contains(['set', 'not set'], widget.displayOperator) ? ' hidden' : ''}">
+ <div t-attf-class="o_ds_value_cell#{_.contains(['set', 'not set'], widget.displayOperator) ? ' d-none' : ''}">
<t t-if="widget.selectionChoices !== null">
<select class="o_domain_leaf_value_input o_input">
<option t-foreach="widget.selectionChoices" t-as="val"
@@ -705,13 +700,13 @@
<t t-else="">
<t t-if="_.contains(['in', 'not in'], widget.operator)">
<div class="o_domain_leaf_value_input">
- <span class="badge" t-foreach="widget.displayValue" t-as="val">
+ <span class="badge badge-pill" t-foreach="widget.displayValue" t-as="val">
<t t-esc="val"/> <i class="o_domain_leaf_value_remove_tag_button fa fa-times" t-att-data-value="val" role="img" aria-label="Remove tag" title="Remove tag"/>
</span>
</div>
<div class="o_domain_leaf_value_tags">
<input placeholder="Add new value" type="text" class="o_input"/>
- <button class="btn btn-xs btn-primary fa fa-plus o_domain_leaf_value_add_tag_button" aria-label="Add tag" title="Add tag"/>
+ <button class="btn btn-sm btn-primary fa fa-plus o_domain_leaf_value_add_tag_button" aria-label="Add tag" title="Add tag"/>
</div>
</t>
<t t-else="">
@@ -747,9 +742,9 @@
<div aria-atomic="true" 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 role="alert" class="fa fa-exclamation-triangle o_field_selector_warning hidden" title="Invalid field chain" aria-label="Invalid field chain"/>
+ <i role="alert" class="fa fa-exclamation-triangle o_field_selector_warning d-none" title="Invalid field chain" aria-label="Invalid field chain"/>
</div>
- <div t-if="!widget.options.readonly" class="o_field_selector_popover hidden" tabindex="0">
+ <div t-if="!widget.options.readonly" class="o_field_selector_popover d-none" tabindex="0">
<div class="o_field_selector_popover_header text-center">
<i class="fa fa-arrow-left o_field_selector_popover_option o_field_selector_prev_page" title="Previous" role="img" aria-label="Previous"/>
<div class="o_field_selector_title"/>
@@ -806,10 +801,10 @@
t-att-id="widget.idForLabel"/>
</t>
<t t-name="FieldRadio.button">
- <div class="o_radio_item" aria-atomic="true">
- <input type="radio" class="o_radio_input" t-att-checked="checked ? true : undefined"
+ <div class="custom-control custom-radio o_radio_item" aria-atomic="true">
+ <input type="radio" class="custom-control-input o_radio_input" t-att-checked="checked ? true : undefined"
t-att-data-value="value[0]" t-att-data-index="index" t-att-id="id"/>
- <label class="o_form_label" t-att-for="id"><t t-esc="value[1]"/></label>
+ <label class="custom-control-label o_form_label" t-att-for="id"><t t-esc="value[1]"/></label>
</div>
</t>
@@ -834,12 +829,12 @@
t-att-id="widget.idForLabel"/>
<a role="button" class="o_dropdown_button" draggable="false"/>
</div>
- <button type="button" t-if="!widget.nodeOptions.no_open" class="fa fa-external-link btn btn-default o_external_button" tabindex="-1" draggable="false" aria-label="External link" title="External link"/>
+ <button type="button" t-if="!widget.nodeOptions.no_open" class="fa fa-external-link btn btn-secondary o_external_button" tabindex="-1" draggable="false" aria-label="External link" title="External link"/>
</div>
</t>
<t t-name="FieldReference" t-extend="FieldMany2One">
<t t-jquery=".o_input_dropdown" t-operation="before">
- <select t-att-class="'o_input o_field_widget' + (widget.nodeOptions.hide_model and ' hidden' or '')">
+ <select t-att-class="'o_input o_field_widget' + (widget.nodeOptions.hide_model and ' d-none' or '')">
<option/>
<option t-foreach="widget.field.selection" t-as="model" t-att-value="model[0]"><t t-esc="model[1]"/></option>
</select>
@@ -849,7 +844,7 @@
<t t-foreach="elements" t-as="el">
<t t-set="color" t-value="el[colorField] || 0"/>
<t t-set="colornames" t-value="['No color', 'Red', 'Orange', 'Yellow', 'Light blue', 'Dark purple', 'Salmon pink', 'Medium blue', 'Dark blue', 'Fushia', 'Green', 'Purple']"/>
- <button t-attf-class="badge dropdown o_tag_color_#{color}" t-att-data-color="color" t-att-data-index="el_index" t-att-data-id="el.id" t-attf-title="Tag color: #{colornames[color]}">
+ <button t-attf-class="badge badge-pill dropdown o_tag_color_#{color}" t-att-data-color="color" t-att-data-index="el_index" t-att-data-id="el.id" t-attf-title="Tag color: #{colornames[color]}">
<span class="o_badge_text"><span role="img" t-attf-aria-label="Tag color: #{colornames[color]}"/><t t-esc="el.display_name"/></span>
<a t-if="!readonly" class="fa fa-times o_delete" title="Delete" aria-label="Delete"/>
</button>
@@ -873,10 +868,10 @@
<div role="menuitem" class="o_hide_in_kanban"
t-att-data-id="tag_id"
t-att-data-color="0">
- <div class="o_checkbox">
- <input type="checkbox"/>
- <span/>
- </div> Hide in Kanban
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox" id="o_hide_in_kanban_checkbox" class="custom-control-input"/>
+ <label for="o_hide_in_kanban_checkbox" class="custom-control-label">Hide in Kanban</label>
+ </div>
</div>
</li>
</ul>
@@ -901,12 +896,12 @@
</t>
<t t-name="FieldStatus.content">
<t t-if="selection_folded.length">
- <button type="button" class="btn btn-sm o_arrow_button btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">More <span class="caret"/></button>
- <ul class="dropdown-menu o-status-more" role="menu">
- <li t-foreach="selection_folded" t-as="i">
+ <button type="button" class="btn o_arrow_button btn-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">More</button>
+ <div class="dropdown-menu o-status-more" role="menu">
+ <t t-foreach="selection_folded" t-as="i">
<t t-call="FieldStatus.content.button"/>
- </li>
- </ul>
+ </t>
+ </div>
</t>
<t t-foreach="selection_unfolded.reverse()" t-as="i">
<t t-call="FieldStatus.content.button"/>
@@ -915,15 +910,15 @@
<t t-name="FieldStatus.content.button">
<t t-set="disabled" t-value="!clickable"/>
<button type="button" t-att-data-value="i.id" disabled="disabled" title="Current state" aria-pressed="true"
- class="btn btn-sm o_arrow_button btn-primary disabled" t-if="i.selected" aria-current="step">
+ class="btn o_arrow_button btn-primary disabled" t-if="i.selected" aria-current="step">
<t t-esc="i.display_name" role="img" t-attf-aria-label="#{i.display_name} is current state"/>
</button>
<button type="button" t-att-data-value="i.id" disabled="disabled" title="Not active state" aria-pressed="false"
- class="btn btn-sm o_arrow_button btn-default disabled" t-if="!i.selected and disabled">
+ class="btn o_arrow_button btn-secondary disabled" t-if="!i.selected and disabled">
<t t-esc="i.display_name" role="img" t-attf-aria-label="#{i.display_name} is not current state"/>
</button>
<button type="button" t-att-data-value="i.id" title="Not active state, click to change it" aria-pressed="false"
- class="btn btn-sm o_arrow_button btn-default" t-if="!i.selected and !disabled">
+ class="btn o_arrow_button btn-secondary" t-if="!i.selected and !disabled">
<t t-esc="i.display_name" role="img" t-attf-aria-label="Click to change current state to #{i.display_name}"/>
</button>
</t>
@@ -931,8 +926,8 @@
<div class="o_field_image" aria-atomic="true">
<t t-if="widget.mode !== 'readonly'">
<div class="o_form_image_controls">
- <button class="fa fa-pencil fa-lg pull-left o_select_file_button" title="Edit" aria-label="Edit"/>
- <button class="fa fa-trash-o fa-lg pull-right o_clear_file_button" title="Clear" aria-label="Clear"/>
+ <button class="fa fa-pencil fa-lg float-left o_select_file_button" title="Edit" aria-label="Edit"/>
+ <button class="fa fa-trash-o fa-lg float-right o_clear_file_button" title="Clear" aria-label="Clear"/>
<span class="o_form_binary_progress">Uploading...</span>
<t t-call="HiddenInputFile">
@@ -944,19 +939,19 @@
</div>
</t>
<t t-name="FieldBinaryImage-img">
- <img class="img img-responsive"
+ <img class="img img-fluid"
alt="Binary file"
t-att-src='url'
t-att-border="widget.readonly ? 0 : 1"
t-att-name="widget.name"/>
</t>
<t t-name="CopyClipboardText">
- <button class="btn btn-xs btn-primary o_clipboard_button o_btn_text_copy">
+ <button class="btn btn-sm btn-primary o_clipboard_button o_btn_text_copy">
<span class="fa fa-clipboard">Copy Text</span>
</button>
</t>
<t t-name="CopyClipboardChar">
- <button class="btn btn-xs btn-primary o_clipboard_button o_btn_char_copy">
+ <button class="btn btn-sm btn-primary o_clipboard_button o_btn_char_copy">
<span class="fa fa-clipboard">Copy Text</span>
</button>
</t>
@@ -970,9 +965,9 @@
t-att-tabindex="widget.attrs.tabindex"
t-att-autofocus="widget.attrs.autofocus"/>
- <button type="button" class="btn btn-sm btn-primary o_select_file_button" title="Select">Upload your file</button>
- <button type="button" class="btn btn-sm btn-default fa fa-pencil o_select_file_button" title="Select" aria-label="Select"/>
- <button type="button" class="btn btn-sm btn-default fa fa-trash-o o_clear_file_button" title="Clear" aria-label="Clear"/>
+ <button type="button" class="btn btn-primary o_select_file_button" title="Select">Upload your file</button>
+ <button type="button" class="btn btn-secondary fa fa-pencil o_select_file_button" title="Select" aria-label="Select"/>
+ <button type="button" class="btn btn-secondary fa fa-trash-o o_clear_file_button" title="Clear" aria-label="Clear"/>
<span class="o_form_binary_progress">Uploading...</span>
<t t-call="HiddenInputFile">
@@ -1001,9 +996,9 @@
<div class="o_field_pdfviewer" aria-atomic="true">
<div t-if="widget.mode !== 'readonly'" class="o_form_pdf_controls mt8" role="toolbar" aria-label="PDF controls">
<span class="o_form_binary_progress">Uploading...</span>
- <button type="button" class="btn btn-sm btn-primary o_select_file_button" title="Select">Upload your file</button>
- <button class="btn btn-sm btn-default fa fa-pencil o_select_file_button" title="Select" aria-label="Select" type="button"></button>
- <button class="btn btn-sm btn-default fa fa-trash-o o_clear_file_button" title="Clear" aria-label="Clear" type="button"></button>
+ <button type="button" class="btn btn-primary o_select_file_button" title="Select">Upload your file</button>
+ <button class="btn btn-secondary fa fa-pencil o_select_file_button" title="Select" aria-label="Select" type="button"></button>
+ <button class="btn btn-secondary fa fa-trash-o o_clear_file_button" title="Clear" aria-label="Clear" type="button"></button>
</div>
<iframe class="o_pdfview_iframe o_field_pdfviewer"/>
<t t-call="HiddenInputPDFFile">
@@ -1024,7 +1019,7 @@
<div t-name="FieldBinaryFileUploader" t-attf-class="oe_fileupload #{widget.attrs.class ? widget.attrs.class :''}" aria-atomic="true">
<div class="oe_placeholder_files"/>
<div t-if="widget.mode !== 'readonly'" class="oe_add">
- <button class="btn btn-default o_attach" title="Attach"><span class="fa fa-paperclip" aria-label="Attach"/> <t t-esc="widget.string"/></button>
+ <button class="btn btn-secondary o_attach" title="Attach"><span class="fa fa-paperclip" aria-label="Attach"/> <t t-esc="widget.string"/></button>
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
<t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
@@ -1045,7 +1040,7 @@
<div t-foreach="widget.value.data" t-as="file" class="oe_attachment">
<t t-if="!file.data.upload">
<div>
- <a href="#" class="fa fa-times pull-right oe_delete" title="Delete this file" aria-label="Delete this file" t-att-data-id="file.data.id"/>
+ <a href="#" class="fa fa-times float-right oe_delete" title="Delete this file" aria-label="Delete this file" t-att-data-id="file.data.id"/>
<t t-raw="file.data.name || file.data.filename"/>
</div>
<a class="o_image" target="_blank" t-att-href="widget.metadata[file.id] ? widget.metadata[file.id].url : false"
@@ -1069,71 +1064,67 @@
<t t-if="widget.items.length !== 0">
<t t-set="group" t-value="0"/>
<t t-foreach="widget.items" t-as="item">
- <li t-if="group !== item.groupId" class="divider" data-removable="1"/>
- <li t-att-class="'o_menu_item ' + (item.isActive ? 'selected ' : '')"
+ <div t-if="group !== item.groupId" class="dropdown-divider" data-removable="1"/>
+ <div t-attf-class="o_menu_item#{item.isActive ? ' selected ' : ''}"
t-att-data-id="item.itemId">
- <a href="#">
+ <a href="#" class="dropdown-item">
<t t-esc="item.description"/>
<span t-if="item.isRemovable" t-att-data-id="item.itemId" class="o_trash_button" > <span class="fa fa-trash-o"></span> </span>
<span t-if="item.hasOptions" t-att-data-id="item.itemId" class="o_submenu_switcher">
<span t-att-class="item.isOpen ? 'fa fa-caret-down' : 'fa fa-caret-right'"></span>
</span>
</a>
- <ul t-if="item.hasOptions &amp;&amp; item.isOpen">
+ <ul t-if="item.hasOptions &amp;&amp; item.isOpen" class="list-unstyled">
<t t-set="subgroup" t-value="0"/>
<t t-foreach="_.values(item.options)" t-as="option">
- <li t-if="subgroup !== option.groupId" class="divider" data-removable="1"/>
- <li t-att-class="'o_item_option ' + (item.currentOptionId === option.optionId ? 'selected': '')"
+ <li t-if="subgroup !== option.groupId" class="dropdown-divider" data-removable="1"/>
+ <li t-attf-class="o_item_option#{item.currentOptionId === option.optionId ? ' selected': ''}"
t-att-data-item_id="item.itemId" t-att-data-option_id="option.optionId">
- <a href="#"><t t-esc="option.description"/></a>
+ <a href="#" class="dropdown-item pl-5"><t t-esc="option.description"/></a>
</li>
<t t-set="subgroup" t-value="option.groupId"/>
</t>
</ul>
- </li>
+ </div>
<t t-set="group" t-value="item.groupId"/>
</t>
</t>
</t>
-<div t-name="web.DropdownMenu" t-att-class="widget.dropdownStyle.el.class" t-att="widget.dropdownStyle.el.attrs" >
+<div t-name="web.DropdownMenu" t-att-class="widget.dropdownStyle.el.class" t-att="widget.dropdownStyle.el.attrs">
<button t-att-class="widget.dropdownStyle.mainButton.class" data-toggle="dropdown" aria-expanded="false" tabindex="-1">
- <span t-att-class="widget.dropdownIcon"/> <t t-esc="widget.dropdownTitle"/> <span t-att-class="widget.dropdownSymbol"/>
+ <span t-att-class="widget.dropdownIcon"/> <t t-esc="widget.dropdownTitle"/> <span t-if="widget.dropdownSymbol" t-att-class="widget.dropdownSymbol"/>
</button>
- <ul class="dropdown-menu o_dropdown_menu" role="menu">
+ <div class="dropdown-menu o_dropdown_menu" role="menu">
<t t-call="DropdownMenu.MenuItems"/>
- </ul>
+ </div>
</div>
<t t-name="GroupbyMenuGenerator">
- <li t-if="Object.keys(widget.presentedFields).length !== 0 &amp;&amp; widget.items.length !== 0" class="o_generator_menu divider"/>
- <li t-if="Object.keys(widget.presentedFields).length !== 0" class="o_generator_menu o_add_custom_group ">
- <a href="#">Add Custom Group</a>
- </li>
- <li t-if="widget.generatorMenuIsOpen" class="o_generator_menu">
- <select class="o_input o_group_selector o_add_group">
+ <div t-if="Object.keys(widget.presentedFields).length !== 0 &amp;&amp; widget.items.length !== 0" class="dropdown-divider o_generator_menu"/>
+ <button t-if="Object.keys(widget.presentedFields).length !== 0" type="button" class="dropdown-item o_generator_menu o_add_custom_group">Add Custom Group</button>
+ <div t-if="widget.generatorMenuIsOpen" class="dropdown-item-text o_generator_menu">
+ <select class="w-auto o_input o_group_selector o_add_group">
<t t-foreach="widget.presentedFields" t-as="field">
<option t-att-value="field.name"><t t-esc="field.string"/></option>
</t>
</select>
- </li>
- <li t-if="widget.generatorMenuIsOpen" class="o_generator_menu">
- <button type="button" class="btn btn-primary btn-sm o_apply_group o_add_group" tabindex="-1">Apply</button>
- </li>
+ </div>
+ <div t-if="widget.generatorMenuIsOpen" class="dropdown-item-text o_generator_menu">
+ <button type="button" class="btn btn-primary o_apply_group o_add_group" tabindex="-1">Apply</button>
+ </div>
</t>
<t t-name="FiltersMenuGenerator">
- <li class="divider"/>
- <li t-if="Object.keys(widget.fields).length !== 0" class="o_add_custom_filter o_closed_menu">
- <a href="#">Add Custom Filter</a>
- </li>
- <li class="o_add_filter_menu">
- <button class="btn btn-primary btn-sm o_apply_filter" type="button">Apply</button>
- <button class="btn btn-default btn-sm o_add_condition" type="button">
+ <div class="dropdown-divider"/>
+ <button t-if="Object.keys(widget.fields).length !== 0" type="button" class="dropdown-item o_add_custom_filter o_closed_menu">Add Custom Filter</button>
+ <div class="dropdown-item-text o_add_filter_menu">
+ <button class="btn btn-primary o_apply_filter" type="button">Apply</button>
+ <button class="btn btn-secondary o_add_condition" type="button">
<span class="fa fa-plus-circle"/>
Add a condition
</button>
- </li>
+ </div>
</t>
@@ -1144,14 +1135,14 @@
</div>
<t t-name="SearchViewMobile">
<div class="o_searchview" role="search" aria-autocomplete="list">
- <button class="o_enable_searchview btn btn-sm fa fa-search"/>
+ <button class="o_enable_searchview btn fa fa-search"/>
<div class="o_mobile_search o_hidden">
<div class="o_mobile_search_header">
- <span class="o_mobile_search_close pull-left mt16 mb16 mr8 ml16">
+ <span class="o_mobile_search_close float-left mt16 mb16 mr8 ml16">
<i class="fa fa-arrow-left"/>
- <strong class="pull-right ml8">FILTER</strong>
+ <strong class="float-right ml8">FILTER</strong>
</span>
- <span class="pull-right o_mobile_search_clear_facets mt16 mr16">CLEAR</span>
+ <span class="float-right o_mobile_search_clear_facets mt16 mr16">CLEAR</span>
</div>
<div class="o_searchview_input_container"/>
<div class="o_mobile_search_filter o_search_options mb8 mt8 ml16 mr16"/>
@@ -1173,15 +1164,20 @@
<t t-esc="widget.model.get('label') + (widget.optionLabel ? (': ' + widget.optionLabel) : '')"/>
</span>
<t t-name="SearchView.autocomplete">
- <ul class="dropdown-menu o_searchview_autocomplete" role="menu"></ul>
+ <div class="dropdown-menu o_searchview_autocomplete" role="menu"/>
</t>
<t t-name="SearchView.filters">
- <li t-foreach="widget.filters" t-as="filter" t-if="!filter.visible || filter.visible()"
- t-att-title="filter.attrs.string ? filter.attrs.help : undefined"
- t-att-data-index="filter_index">
- <a role="menuitem" href="#"><t t-esc="filter.attrs.string or filter.attrs.help or filter.attrs.name or 'Ω'"/></a>
- </li>
+ <t t-foreach="widget.filters" t-as="filter">
+ <a t-if="!filter.visible || filter.visible()"
+ href="#"
+ class="dropdown-item"
+ t-att-title="filter.attrs.string ? filter.attrs.help : undefined"
+ t-att-data-index="filter_index"
+ role="menuitem">
+ <t t-esc="filter.attrs.string or filter.attrs.help or filter.attrs.name or 'Ω'"/>
+ </a>
+ </t>
</t>
<t t-name="SearchView.field">
<label t-att-class="'oe_label' + (attrs.help ? '_help' : '')"
@@ -1243,7 +1239,7 @@
</div>
</t>
<t t-name="SearchView.extended_search.proposition">
- <li role="menuitem" class="o_filter_condition">
+ <div role="menuitem" class="dropdown-item-text o_filter_condition">
<span class="o_or_filter">or</span>
<span>
<select class="o_input o_searchview_extended_prop_field">
@@ -1258,7 +1254,7 @@
</span>
<select class="o_input o_searchview_extended_prop_op"/>
<span class="o_searchview_extended_prop_value"/>
- </li>
+ </div>
</t>
<t t-name="SearchView.extended_search.proposition.float">
<input class="o_input"
@@ -1276,33 +1272,37 @@
</t>
<div t-name="SearchView.FavoriteMenu" class="btn-group o_dropdown">
- <button class="o_dropdown_toggler_btn btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false" tabindex="-1" aria-label="Favorites" title="Favorites">
- <span class="fa fa-star"/> Favorites <span t-attf-class="#{widget.isMobile ? 'fa fa-chevron-right pull-right mt4' : 'caret'}"/>
+ <button t-attf-class="o_dropdown_toggler_btn btn btn-secondary dropdown-toggle#{widget.isMobile ? ' o-no-caret' : ''}" data-toggle="dropdown" aria-expanded="false" tabindex="-1" aria-label="Favorites" title="Favorites">
+ <span class="fa fa-star"/> Favorites <span t-if="widget.isMobile" class="fa fa-chevron-right float-right mt4"/>
</button>
- <ul class="dropdown-menu o_favorites_menu" role="menu">
- <li class="divider user_filter"/>
- <li class="divider shared_filter"/>
- <li class="o_save_search o_closed_menu">
- <a role="menuitem" href="#">Save current search</a>
- </li>
- <li role="menuitem" class="o_save_name">
- <input type="text"></input>
- </li>
- <li role="menuitem" class="o_save_name">
- <span><div class="o_checkbox"><input type="checkbox"/><span/></div> Use by default</span>
- </li>
- <li role="menuitem" class="o_save_name">
- <span><div class="o_checkbox"><input type="checkbox"/><span/></div> Share with all users </span><span class="fa fa-users" role="img" aria-label="Users" title="Users"/>
- </li>
- <li class="o_save_name">
- <button role="menuitem" type="button" class="btn btn-primary btn-sm">Save</button>
- </li>
- </ul>
+ <div class="dropdown-menu o_favorites_menu" role="menu">
+ <div class="dropdown-divider user_filter"/>
+ <div class="dropdown-divider shared_filter"/>
+ <a role="menuitem" href="#" class="dropdown-item o_save_search o_closed_menu">Save current search</a>
+ <div role="menuitem" class="dropdown-item-text o_save_name">
+ <input type="text" class="o_input"></input>
+ </div>
+ <div role="menuitem" class="dropdown-item-text o_save_name">
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox" id="o_fav_menu_use_by_default" class="custom-control-input"/>
+ <label for="o_fav_menu_use_by_default" class="custom-control-label">Use by default</label>
+ </div>
+ </div>
+ <div role="menuitem" class="dropdown-item-text o_save_name">
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox" id="o_fav_menu_share_all_users" class="custom-control-input"/>
+ <label for="o_fav_menu_share_all_users" class="custom-control-label">Share with all users <span class="fa fa-users" role="img" aria-label="Users" title="Users"/></label>
+ </div>
+ </div>
+ <div class="dropdown-item-text o_save_name">
+ <button role="menuitem" type="button" class="btn btn-primary">Save</button>
+ </div>
+ </div>
</div>
<div t-name="ExportDialog" class="o_export">
<div class="row">
- <div class="col-md-6">
+ <div class="col-lg-6">
<strong>What do you want to do?</strong>
<div class="o_import_compat">
<div class="radio">
@@ -1319,7 +1319,7 @@
</div>
</div>
</div>
- <div class="col-md-6">
+ <div class="col-lg-6">
<strong>Export Format:</strong>
<div class="o_export_format"/>
</div>
@@ -1331,15 +1331,15 @@
<div class="o_left_field_panel"/>
</div>
<div class="o_center_panel">
- <button type="button" class="btn btn-sm btn-default o_add_field">Add</button>
- <button type="button" class="btn btn-sm btn-default o_remove_field">Remove</button>
- <button type="button" class="btn btn-sm btn-default o_remove_all_field">Remove All</button>
- <button type="button" class="btn btn-sm btn-default o_move_up">Move Up</button>
- <button type="button" class="btn btn-sm btn-default o_move_down">Move Down</button>
+ <button type="button" class="btn btn-secondary o_add_field">Add</button>
+ <button type="button" class="btn btn-secondary o_remove_field">Remove</button>
+ <button type="button" class="btn btn-secondary o_remove_all_field">Remove All</button>
+ <button type="button" class="btn btn-secondary o_move_up">Move Up</button>
+ <button type="button" class="btn btn-secondary o_move_down">Move Down</button>
</div>
<div class="o_right_panel">
<h4>
- <a href="#" class="pull-right o_toggle_save_list">Save fields list</a>
+ <a href="#" class="float-right o_toggle_save_list">Save fields list</a>
Fields to export
</h4>
<div class="o_save_list"/>
@@ -1363,7 +1363,7 @@
</t>
</t>
<t t-name="Export.SaveList">
- <label>Save as:</label> <input type="text"/><button type="button" class="btn btn-sm btn-default">Ok</button>
+ <label>Save as:</label> <input type="text"/><button type="button" class="btn btn-secondary">Ok</button>
</t>
<t t-name="Export.SavedList">
<label>Saved exports: </label>
@@ -1373,7 +1373,7 @@
<option t-att-value="export.id"><t t-esc="export.name"/></option>
</t>
</select>
- <button type="button" class="btn btn-sm btn-default o_delete_exported_list">Delete</button>
+ <button type="button" class="btn btn-secondary o_delete_exported_list">Delete</button>
</t>
<t t-name="Throbber">
@@ -1398,11 +1398,10 @@
<div aria-atomic="true">
<div t-foreach="widget.m2mValues" t-as="m2m_value">
<t t-set="id_for_label" t-value="'o_many2many_checkbox_' + _.uniqueId()"/>
- <div class="o_checkbox">
- <input type="checkbox" t-att-id="id_for_label" t-att-data-record-id="JSON.stringify(m2m_value[0])"/>
- <span/>
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox" t-att-id="id_for_label" class="custom-control-input" t-att-data-record-id="JSON.stringify(m2m_value[0])"/>
+ <label t-att-for="id_for_label" class="custom-control-label o_form_label"><t t-esc="m2m_value[1]"/></label>
</div>
- <label t-att-for="id_for_label" class="o_form_label"><t t-esc="m2m_value[1]"/></label>
</div>
</div>
</t>
@@ -1420,14 +1419,14 @@
<span class="o_pager_counter">
<span class="o_pager_value"></span> / <span class="o_pager_limit"></span>
</span>
- <span class="btn-group btn-group-sm" aria-atomic="true">
+ <span class="btn-group" aria-atomic="true">
<!-- accesskeys not wanted in X2Many widgets -->
<t t-if="widget.options.withAccessKey">
<t t-set="att_prev" t-value="{'accesskey': 'p'}" />
<t t-set="att_next" t-value="{'accesskey': 'n'}" />
</t>
- <button type="button" class="fa fa-chevron-left btn btn-icon o_pager_previous" t-att="att_prev" aria-label="Previous" title="Next" tabindex="-1"/>
- <button type="button" class="fa fa-chevron-right btn btn-icon o_pager_next" t-att="att_next" aria-label="Next" title="Next" tabindex="-1"/>
+ <button type="button" class="fa fa-chevron-left btn btn-secondary o_pager_previous" t-att="att_prev" aria-label="Previous" title="Next" tabindex="-1"/>
+ <button type="button" class="fa fa-chevron-right btn btn-secondary o_pager_next" t-att="att_next" aria-label="Next" title="Next" tabindex="-1"/>
</span>
</div>
@@ -1457,36 +1456,36 @@
<t t-name="UserMenu">
<li class="o_user_menu">
<a class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" href="#">
- <img class="img-circle oe_topbar_avatar" t-att-src="_s + '/web/static/src/img/user_menu_avatar.png'" alt="Avatar"/>
+ <img class="rounded-circle oe_topbar_avatar" t-att-src="_s + '/web/static/src/img/user_menu_avatar.png'" alt="Avatar"/>
<span class="oe_topbar_name"/>
</a>
- <ul class="dropdown-menu" role="menu">
+ <div class="dropdown-menu dropdown-menu-right" role="menu">
<t t-call="UserMenu.Actions"/>
- </ul>
+ </div>
</li>
</t>
<t t-name="UserMenu.Actions">
- <li><a role="menuitem" href="#" data-menu="documentation">Documentation</a></li>
- <li><a role="menuitem" href="#" data-menu="support">Support</a></li>
- <li role="separator" class="divider"/>
- <li><a role="menuitem" href="#" data-menu="settings">Preferences</a></li>
- <li><a role="menuitem" href="#" data-menu="account">My Odoo.com account</a></li>
- <li><a role="menuitem" href="#" data-menu="logout">Log out</a></li>
+ <a role="menuitem" href="#" data-menu="documentation" class="dropdown-item">Documentation</a>
+ <a role="menuitem" href="#" data-menu="support" class="dropdown-item">Support</a>
+ <div role="separator" class="dropdown-divider"/>
+ <a role="menuitem" href="#" data-menu="settings" class="dropdown-item">Preferences</a>
+ <a role="menuitem" href="#" data-menu="account" class="dropdown-item">My Odoo.com account</a>
+ <a role="menuitem" href="#" data-menu="logout" class="dropdown-item">Log out</a>
</t>
<t t-name="SwitchCompanyMenu">
<li class="o_switch_company_menu">
<a class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" href="#" aria-label="Dropdown menu" title="Dropdown menu">
- <span t-attf-class="#{widget.isMobile ? 'fa fa-building-o' : 'oe_topbar_name'}"/> <span class="caret"/>
+ <span t-attf-class="#{widget.isMobile ? 'fa fa-building-o' : 'oe_topbar_name'}"/>
</a>
- <ul class="dropdown-menu" role="menu"/>
+ <div class="dropdown-menu dropdown-menu-right" role="menu"/>
</li>
</t>
<t t-name="EnterpriseUpgrade">
<div class="row" role="status">
- <div class="col-xs-6">
+ <div class="col-6">
Get this feature and much more with Odoo Enterprise!
<ul class="list-unstyled">
<li><i class="fa fa-check"></i> Access to all Enterprise Apps</li>
@@ -1497,8 +1496,8 @@
<li><a href="http://www.odoo.com/editions" target="_blank"><i class="fa fa-plus"></i> And more</a></li>
</ul>
</div>
- <div class="col-xs-6">
- <img class="img-responsive" t-att-src='_s + "/web/static/src/img/enterprise_upgrade.jpg"' draggable="false" alt="Upgrade to enterprise"/>
+ <div class="col-6">
+ <img class="img-fluid" t-att-src='_s + "/web/static/src/img/enterprise_upgrade.jpg"' draggable="false" alt="Upgrade to enterprise"/>
</div>
</div>
</t>
@@ -1506,7 +1505,7 @@
<t t-name="BaseSetting.Tabs">
<t t-foreach="tabItems" t-as="tab">
<div class="tab" t-attf-data-key="#{tab.key}" role="tab">
- <div class="icon hidden-xs" t-attf-style="background : url('#{imgurl}') no-repeat center;background-size:contain;"/> <span class="app_name"><t t-esc="tab.string"/></span>
+ <div class="icon d-none d-md-block" t-attf-style="background : url('#{imgurl}') no-repeat center;background-size:contain;"/> <span class="app_name"><t t-esc="tab.string"/></span>
</div>
</t>
</t>
@@ -1519,9 +1518,9 @@
</t>
<t t-name="AttachDocument">
- <button class="btn btn-sm btn-default o_attachment_button">
+ <button class="btn btn-secondary o_attachment_button">
<span class="o_attach_document"><t t-esc="widget.node.attrs.string"/></span>
- <span class="hide">
+ <span class="d-none">
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileuploadID"/>
<t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
diff --git a/addons/web/static/src/xml/dialog.xml b/addons/web/static/src/xml/dialog.xml
index e55a17f26ef..955deb0e7c8 100644
--- a/addons/web/static/src/xml/dialog.xml
+++ b/addons/web/static/src/xml/dialog.xml
@@ -7,8 +7,8 @@
<div class="modal-dialog">
<div class="modal-content">
<header class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-label="Close" tabindex="-1">×</button>
<h4 class="modal-title"><t t-raw="title"/><span class="o_subtitle text-muted small"><t t-esc="subtitle"/></span></h4>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close" tabindex="-1">×</button>
</header>
<main class="modal-body"/>
<footer class="modal-footer"/>
diff --git a/addons/web/static/src/xml/kanban.xml b/addons/web/static/src/xml/kanban.xml
index 4b62f52cda8..e95c91e1998 100644
--- a/addons/web/static/src/xml/kanban.xml
+++ b/addons/web/static/src/xml/kanban.xml
@@ -2,7 +2,7 @@
<t t-name="KanbanView.buttons">
<div>
- <button type="button" t-attf-class="btn #{btnClass} btn-sm o-kanban-button-new" accesskey="c">
+ <button type="button" t-attf-class="btn #{btnClass} o-kanban-button-new" accesskey="c">
<t t-esc="create_text || _t('Create')"/>
</button>
</div>
@@ -16,18 +16,18 @@
<span t-attf-id="#kanban_header_#{widget.id or widget.db_id}" class="o_column_title"><t t-esc="widget.title"/></span>
<span class="o_column_unfold"><i class="fa fa-arrows-h" role="img" aria-label="Unfold" title="Unfold"/></span>
<span class="o_kanban_config dropdown">
- <a class="dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-gear" role="img" aria-label="Settings" title="Settings"/></a>
- <ul class="dropdown-menu" role="menu">
- <li><a role="menuitem" class="o_kanban_toggle_fold" href="#">Fold</a></li>
+ <a class="dropdown-toggle o-no-caret" data-toggle="dropdown" href="#"><i class="fa fa-gear" role="img" aria-label="Settings" title="Settings"/></a>
+ <div class="dropdown-menu" role="menu">
+ <a role="menuitem" class="dropdown-item o_kanban_toggle_fold" href="#">Fold</a>
<t t-if="widget.grouped_by_m2o">
- <li t-if="widget.editable and widget.id"><a role="menuitem" class="o_column_edit" href="#">Edit Stage</a></li>
- <li t-if="widget.deletable and widget.id"><a role="menuitem" class="o_column_delete" href="#">Delete</a></li>
+ <a t-if="widget.editable and widget.id" role="menuitem" class="dropdown-item o_column_edit" href="#">Edit Stage</a>
+ <a t-if="widget.deletable and widget.id" role="menuitem" class="dropdown-item o_column_delete" href="#">Delete</a>
</t>
<t t-if="widget.has_active_field">
- <li><a class="o_column_archive_records" href="#">Archive All</a></li>
- <li><a class="o_column_unarchive_records" href="#">Unarchive All</a></li>
+ <a href="#" class="dropdown-item o_column_archive_records">Archive All</a>
+ <a href="#" class="dropdown-item o_column_unarchive_records">Unarchive All</a>
</t>
- </ul>
+ </div>
</span>
<span t-if="widget.quick_create" class="o_kanban_quick_add"><i class="fa fa-plus" role="img" aria-label="Quick add" title="Quick add"/></span>
</div>
@@ -51,15 +51,15 @@
<div class="o_quick_create_unfolded">
<div class="o_kanban_header">
<div class="input-group">
- <input type="text" class="o_input" placeholder="Column title"/>
- <span class="input-group-btn">
- <button class="btn btn-sm btn-primary o_kanban_add" type="button">Add</button>
+ <input type="text" class="form-control o_input" placeholder="Column title"/>
+ <span class="input-group-append">
+ <button class="btn btn-primary o_kanban_add" type="button">Add</button>
</span>
</div>
<t t-if="widget.examples">
<a href="#" role="button" class="btn-link o_kanban_examples">Examples</a>
</t>
- <span class="o_discard_msg text-muted pull-right">Esc to discard</span>
+ <span class="o_discard_msg text-muted float-right">Esc to discard</span>
</div>
<div class="o_kanban_muted_record"/>
<div class="o_kanban_muted_record"/>
@@ -70,9 +70,9 @@
<t t-name="KanbanView.RecordQuickCreate.buttons">
<div>
- <button class="btn btn-sm btn-primary o_kanban_add">Add</button>
- <button class="btn btn-sm btn-primary o_kanban_edit">Edit</button>
- <button class="btn btn-sm btn-default o_kanban_cancel ml8">Discard</button>
+ <button class="btn btn-primary o_kanban_add">Add</button>
+ <button class="btn btn-primary o_kanban_edit">Edit</button>
+ <button class="btn btn-secondary o_kanban_cancel ml8">Discard</button>
</div>
</t>
@@ -124,10 +124,10 @@
<!-- Note: this dialog isn't responsive, but it is not accessible on mobile -->
<div t-name="KanbanView.ExamplesDialog" class="o_kanban_examples_dialog">
<div class="o_kanban_examples_dialog_nav">
- <ul class="nav nav-pills nav-stacked">
+ <ul class="nav nav-pills flex-column">
<t t-foreach="examples" t-as="example">
- <li t-att-class="example_index == 0 and 'active' or None">
- <a t-attf-aria-controls="example_#{example_index}" data-toggle="tab" role="tab" t-attf-href="#example_#{example_index}"> <t t-esc="example.name"/> </a>
+ <li class="nav-item">
+ <a t-attf-aria-controls="example_#{example_index}" data-toggle="tab" role="tab" t-attf-href="#example_#{example_index}" t-attf-class="nav-link#{example_index == 0 and ' active' or ''}"> <t t-esc="example.name"/> </a>
</li>
</t>
</ul>
@@ -158,7 +158,7 @@
<div class="o_kanban_examples_ghost">
<div class="o_ghost_content"/>
<div class="o_ghost_content o_ghost_tag"/>
- <img class="pull-right o_ghost_avatar" src="/base/static/img/avatar.png" alt="Avatar"/>
+ <img class="float-right o_ghost_avatar" src="/base/static/img/avatar.png" alt="Avatar"/>
</div>
</t>
diff --git a/addons/web/static/src/xml/report.xml b/addons/web/static/src/xml/report.xml
index c578add8ce9..49313e8de5a 100644
--- a/addons/web/static/src/xml/report.xml
+++ b/addons/web/static/src/xml/report.xml
@@ -8,14 +8,14 @@
<!-- Buttons of the Control Panel -->
<t t-name="report.client_action.ControlButtons">
<div class="o_report_no_edit_mode">
- <button type="button" class="btn btn-primary btn-sm o_report_print" title="Print">Print</button>
+ <button type="button" class="btn btn-primary o_report_print" title="Print">Print</button>
</div>
<div class="o_edit_mode_available">
- <button type="button" class="btn btn-default btn-sm o_report_edit" title="Edit">Edit</button>
+ <button type="button" class="btn btn-secondary o_report_edit" title="Edit">Edit</button>
</div>
<div class="o_report_edit_mode">
- <button type="button" class="btn btn-primary btn-sm o_report_save" title="Save">Save</button>
- <button type="button" class="btn btn-default btn-sm o_report_discard" title="Discard">Discard</button>
+ <button type="button" class="btn btn-primary o_report_save" title="Save">Save</button>
+ <button type="button" class="btn btn-secondary o_report_discard" title="Discard">Discard</button>
</div>
</t>
</template> \ No newline at end of file
diff --git a/addons/web/static/src/xml/web_calendar.xml b/addons/web/static/src/xml/web_calendar.xml
index 41f772cd52f..3f32dcbd173 100644
--- a/addons/web/static/src/xml/web_calendar.xml
+++ b/addons/web/static/src/xml/web_calendar.xml
@@ -4,7 +4,7 @@
<div class="o_calendar_buttons" role="toolbar" aria-label="Calendar toolbar"/>
<div class="o_calendar_widget" />
</div>
- <div class="o_calendar_sidebar_container hidden-xs">
+ <div class="o_calendar_sidebar_container d-none d-md-block">
<i class="o_calendar_sidebar_toggler fa"/>
<div class="o_calendar_sidebar">
<div class="o_calendar_mini"/>
@@ -21,7 +21,7 @@
<div t-attf-class="o_field_#{name} o_field_type_#{fields[name].type}">
<t t-if="widget.displayFields[name].avatar_field">
<t t-if="!isMobile"><t t-esc="fields[name].string"/>:</t>
- <div class="o_calendar_avatars pull-right">
+ <div class="o_calendar_avatars float-right">
<t t-foreach="widget.getAvatars(record, name, widget.displayFields[name].avatar_field).slice(0,3)" t-as="image"><t t-raw="image"/></t>
<span t-if="record[name].length - 3 > 0">+<t t-esc="record[name].length - 3"/></span>
</div>
@@ -40,22 +40,29 @@
<h3 t-if="widget.title"><t t-esc="widget.title"/></h3>
<div class="o_calendar_filter_items">
<div t-foreach="widget.filters" t-as="filter" t-if="filter.display == null || filter.display" class="o_calendar_filter_item" t-att-data-value="filter.value" t-att-data-id="filter.id">
- <div class="o_checkbox">
- <input type="checkbox" name="selection" t-att-checked="(filter.active ? true : undefined)"/><span/>
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox"
+ t-attf-id="o_calendar_filter_item_#{filter_index}"
+ name="selection"
+ class="custom-control-input"
+ t-att-checked="(filter.active ? true : undefined)"/>
+ <label t-attf-for="o_calendar_filter_item_#{filter_index}"
+ class="custom-control-label">
+ <t t-if="filter.value == 'all'">
+ <span><i class="fa fa-users fa-fw o_cal_avatar" role="img" aria-label="Avatar" title="Avatar"/></span>
+ </t>
+ <t t-if="widget.avatar_field &amp;&amp; (filter.value != 'all')">
+ <img t-attf-src="/web/image/#{widget.avatar_model}/#{filter.value}/#{widget.avatar_field}" class="o_cal_avatar" alt="Avatar"/>
+ </t>
+ <t t-set="color" t-value="widget.getColor(filter.color_index)"/>
+ <span t-if="typeof color === 'number'" t-attf-class="color_filter o_underline_color_#{widget.getColor(filter.color_index)}"><t t-esc="filter.label"/></span>
+ <span t-elif="color" t-attf-style="border-bottom: 4px solid #{color};"><t t-esc="filter.label"/></span>
+ <span t-else=""><t t-esc="filter.label"/></span>
+ </label>
</div>
- <t t-if="filter.value == 'all'">
- <span><i class="fa fa-users fa-fw o_cal_avatar" role="img" aria-label="Avatar" title="Avatar"/></span>
- </t>
- <t t-if="widget.avatar_field &amp;&amp; (filter.value != 'all')">
- <img t-attf-src="/web/image/#{widget.avatar_model}/#{filter.value}/#{widget.avatar_field}" class="o_cal_avatar" alt="Avatar"/>
- </t>
- <t t-set="color" t-value="widget.getColor(filter.color_index)"/>
- <span t-if="typeof color === 'number'" t-attf-class="color_filter o_underline_color_#{widget.getColor(filter.color_index)}"><t t-esc="filter.label"/></span>
- <span t-elif="color" t-attf-style="border-bottom: 4px solid #{color};"><t t-esc="filter.label"/></span>
- <span t-else=""><t t-esc="filter.label"/></span>
<t t-if="filter.id">
<span class="o_remove fa fa-times" title="Remove this favorite from the list" role="img" aria-label="Remove this favorite from the list"/>
- </t>
+ </t>
</div>
</div>
</div>
@@ -64,14 +71,14 @@
<t t-name="CalendarView.buttons">
<div class="o_calendar_buttons">
<t t-if="!isMobile">
- <button class="o_calendar_button_prev btn btn-sm btn-primary" aria-label="Previous" title="Previous"><span class="fa fa-arrow-left"/></button>
- <button class="o_calendar_button_today btn btn-sm btn-primary">Today</button>
- <button class="o_calendar_button_next btn btn-sm btn-primary" aria-label="Next" title="Next"><span class="fa fa-arrow-right"/></button>
+ <button class="o_calendar_button_prev btn btn-primary" aria-label="Previous" title="Previous"><span class="fa fa-arrow-left"/></button>
+ <button class="o_calendar_button_today btn btn-primary">Today</button>
+ <button class="o_calendar_button_next btn btn-primary" aria-label="Next" title="Next"><span class="fa fa-arrow-right"/></button>
</t>
- <div class="btn-group btn-group-sm">
- <button type="button" class="o_calendar_button_day btn btn-sm btn-default">Day</button>
- <button type="button" class="o_calendar_button_week btn btn-sm btn-default">Week</button>
- <button type="button" class="o_calendar_button_month btn btn-sm btn-default">Month</button>
+ <div class="btn-group">
+ <button type="button" class="o_calendar_button_day btn btn-secondary">Day</button>
+ <button type="button" class="o_calendar_button_week btn btn-secondary">Week</button>
+ <button type="button" class="o_calendar_button_month btn btn-secondary">Month</button>
</div>
</div>
</t>
@@ -85,7 +92,7 @@
<main t-name="CalendarView.quick_create" class="o_calendar_quick_create">
<div class="form-group">
- <label for='name' class='control-label'>Summary:</label>
+ <label for='name' class='col-form-label'>Summary:</label>
<input type='text' name='name' class="o_input" t-att-value="widget.dataTemplate.name or None"/>
</div>
</main>