diff options
| author | Christophe Simonis <chs@odoo.com> | 2019-01-09 15:44:05 +0000 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2019-01-09 15:56:53 +0000 |
| commit | 8aa8548d8ab68feb13f3bde51c557db84877e809 (patch) | |
| tree | 930790c1c84a4412db777986f6b2077808560d95 /addons/web/static/src | |
| parent | 55a48e341580a6a400c36b6ba0d7b12ff9997f12 (diff) | |
| parent | 3e4138deaa23b3631dc3fce33cd6d1b3be28ffbd (diff) | |
[MERGE] forward port branch 12.0 up to 3e4138deaa2
closes odoo/odoo#30045
Diffstat (limited to 'addons/web/static/src')
20 files changed, 159 insertions, 52 deletions
diff --git a/addons/web/static/src/js/chrome/action_manager.js b/addons/web/static/src/js/chrome/action_manager.js index c798189c0a0..107c6e314eb 100644 --- a/addons/web/static/src/js/chrome/action_manager.js +++ b/addons/web/static/src/js/chrome/action_manager.js @@ -332,9 +332,6 @@ var ActionManager = Widget.extend({ // update the internal state and the DOM self._pushController(controller); - // toggle the fullscreen mode for actions in target='fullscreen' - self._toggleFullscreen(); - // store the action into the sessionStorage so that it can be // fully restored on F5 self.call('session_storage', 'setItem', 'current_action', action._originalAction); @@ -720,6 +717,9 @@ var ActionManager = Widget.extend({ action: this.getCurrentAction(), controller: controller, }); + + // toggle the fullscreen mode for actions in target='fullscreen' + this._toggleFullscreen(); }, /** * Pushes the given state, with additional information about the given diff --git a/addons/web/static/src/js/core/dialog.js b/addons/web/static/src/js/core/dialog.js index 492ea06c7bd..83eded92c8a 100644 --- a/addons/web/static/src/js/core/dialog.js +++ b/addons/web/static/src/js/core/dialog.js @@ -143,7 +143,11 @@ var Dialog = Widget.extend({ $.when(def).always(self.close.bind(self)); } }); - self.$footer.append($button); + if (self.technical) { + self.$footer.append($button); + } else { + self.$footer.prepend($button); + } }); }, diff --git a/addons/web/static/src/js/core/dom.js b/addons/web/static/src/js/core/dom.js index 848e406c4b2..b8a5b8be3a4 100644 --- a/addons/web/static/src/js/core/dom.js +++ b/addons/web/static/src/js/core/dom.js @@ -506,7 +506,7 @@ var dom = { 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($('<a/>', {role: 'button', href: '#', class: 'nav-link dropdown-toggle o-no-caret', 'data-toggle': 'dropdown', 'aria-expanded': false}) .append($('<i/>', {class: 'fa fa-plus'}))) .append($dropdownMenu); $extraItemsToggle.insertAfter($items.last()); diff --git a/addons/web/static/src/js/tools/debug_manager.js b/addons/web/static/src/js/tools/debug_manager.js index a348f54acd9..f09d8745f04 100644 --- a/addons/web/static/src/js/tools/debug_manager.js +++ b/addons/web/static/src/js/tools/debug_manager.js @@ -365,6 +365,10 @@ DebugManager.include({ views: [[false, 'list'], [false, 'form']], type: 'ir.actions.act_window', domain: [['res_model', '=', this._action.res_model], ['res_id', '=', selectedIDs[0]]], + context: { + default_res_model: this._action.res_model, + default_res_id: selectedIDs[0], + }, }); }, get_metadata: function() { diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index fecbaa5b90c..9706251ed07 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1758,7 +1758,7 @@ var BasicModel = AbstractModel.extend({ model: list.model, method: 'read', args: [_.pluck(data, 'id'), fieldNames], - context: record.context, + context: _.extend({}, record.context, field.context), }).then(function (records) { _.each(records, function (record) { list_records[record.id].data = record; @@ -1833,7 +1833,7 @@ var BasicModel = AbstractModel.extend({ addDef = this._applyX2ManyChange(record, fieldName, { operation: 'ADD_M2M', ids: values - }); + }, viewType); } if (removedIds.length) { var listData = _.map(list.data, function (localId) { @@ -1847,7 +1847,7 @@ var BasicModel = AbstractModel.extend({ } return _.findWhere(listData, {res_id: resID}).id; }), - }); + }, viewType); } return $.when(addDef, removedDef); } @@ -2827,7 +2827,7 @@ var BasicModel = AbstractModel.extend({ var ids = record.data[fieldName] || []; var list = self._makeDataPoint({ count: ids.length, - context: record.context, + context: _.extend({}, record.context, field.context), fieldsInfo: fieldsInfo, fields: view ? view.fields : fieldInfo.relatedFields, limit: fieldInfo.limit, @@ -4325,11 +4325,24 @@ var BasicModel = AbstractModel.extend({ } return def.then(function () { var resIDs = []; - // generate the current count and res_ids list by applying the changes - var currentCount = list.count; var currentResIDs = list.res_ids; - var effectiveLimit = (list.limit || 0) - (list.tempLimitIncrement || 0); - var upperBound = effectiveLimit ? Math.min(list.offset + effectiveLimit, currentCount) : currentCount; + // if new records have been added to the list, their virtual ids have + // been pushed at the end of res_ids (or at the beginning, depending + // on the editable property), ignoring completely the current page + // where the records have actually been created ; for that reason, + // we use orderedResIDs which is a freezed order with the virtual ids + // at the correct position where they were actually inserted ; however, + // when we use orderedResIDs, we must filter out ids that are not in + // res_ids, which correspond to records that have been removed from + // the relation (this information being taken into account in res_ids + // but not in orderedResIDs) + if (list.orderedResIDs) { + currentResIDs = list.orderedResIDs.filter(function (resID) { + return list.res_ids.indexOf(resID) >= 0; + }); + } + var currentCount = currentResIDs.length; + var upperBound = list.limit ? Math.min(list.offset + list.limit, currentCount) : currentCount; var fieldNames = list.getFieldNames(); for (var i = list.offset; i < upperBound; i++) { var resId = currentResIDs[i]; diff --git a/addons/web/static/src/js/views/basic/basic_view.js b/addons/web/static/src/js/views/basic/basic_view.js index d5d6cfa18d5..39444fdfd75 100644 --- a/addons/web/static/src/js/views/basic/basic_view.js +++ b/addons/web/static/src/js/views/basic/basic_view.js @@ -145,6 +145,21 @@ var BasicView = AbstractView.extend({ if (_.difference(fieldViewTypes, recordViewTypes).length) { fieldNames.push(name); } + + if (record.data[name].viewType === 'default') { + // Use case: x2many (tags) in x2many list views + // When opening the x2many record form view, the + // x2many will be reloaded but it may not have + // the same fields (ex: tags in list and list in + // form) so we need to merge the fieldsInfo to + // avoid losing the initial fields (display_name) + var defaultFieldInfo = record.data[name].fieldsInfo.default; + _.each(fieldViews, function (fieldView) { + _.each(fieldView.fieldsInfo, function (x2mFieldInfo) { + _.defaults(x2mFieldInfo, defaultFieldInfo); + }); + }); + } } } // Many2one: context is not the same between the different views diff --git a/addons/web/static/src/js/views/calendar/calendar_model.js b/addons/web/static/src/js/views/calendar/calendar_model.js index 1f8c9423cac..7c06a7d818d 100644 --- a/addons/web/static/src/js/views/calendar/calendar_model.js +++ b/addons/web/static/src/js/views/calendar/calendar_model.js @@ -244,18 +244,18 @@ return AbstractModel.extend({ this.setDate(this.data.target_date.clone().add(-1, this.data.scale)); }, /** - * @todo: this should not work. it ignores the domain/context - * * @override - * @param {any} _handle ignored - * @param {Object} params + * @param {Object} [params.context] * @param {Array} [params.domain] * @returns {Deferred} */ - reload: function (_handle, params) { + reload: function (handle, params) { if (params.domain) { this.data.domain = params.domain; } + if (params.context) { + this.data.context = params.context; + } return this._loadCalendar(); }, /** @@ -385,6 +385,9 @@ return AbstractModel.extend({ * @returns {Object} */ _getFullCalendarOptions: function () { + var week_start = _t.database.parameters.week_start || 0; + // calendar uses index 0 for Sunday but Odoo stores it as 7 + week_start = week_start % 7; return { defaultView: (this.mode === "month")? "month" : ((this.mode === "week")? "agendaWeek" : ((this.mode === "day")? "agendaDay" : "agendaWeek")), header: false, @@ -404,7 +407,7 @@ return AbstractModel.extend({ monthNamesShort: moment.monthsShort(), dayNames: moment.weekdays(), dayNamesShort: moment.weekdaysShort(), - firstDay: _t.database.parameters.week_start, + firstDay: week_start, slotLabelFormat: _t.database.parameters.time_format.search("%H") != -1 ? 'H:mm': 'h(:mm)a', }; }, diff --git a/addons/web/static/src/js/views/form/form_view.js b/addons/web/static/src/js/views/form/form_view.js index 249f4ec6019..5a00350c68f 100644 --- a/addons/web/static/src/js/views/form/form_view.js +++ b/addons/web/static/src/js/views/form/form_view.js @@ -122,9 +122,14 @@ var FormView = BasicView.extend({ while (matches = regex.exec(attrs.context)) { context[matches[1]] = matches[2]; } + + // Remove *_view_ref coming from parent view + var refinedContext = _.pick(self.loadParams.context, function (value, key) { + return key.indexOf('_view_ref') === -1; + }); defs.push(parent.loadViews( field.relation, - new Context(context, self.userContext, self.loadParams.context).eval(), + new Context(context, self.userContext, refinedContext).eval(), [[null, attrs.mode === 'tree' ? 'list' : attrs.mode]]) .then(function (views) { for (var viewName in views) { 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 57ecc6f4b4e..b526b80a971 100644 --- a/addons/web/static/src/js/views/kanban/kanban_column.js +++ b/addons/web/static/src/js/views/kanban/kanban_column.js @@ -114,7 +114,6 @@ var KanbanColumn = Widget.extend({ revert: 0, delay: 0, items: '> .o_kanban_record:not(.o_updating)', - helper: 'clone', cursor: 'move', over: function () { self.$el.addClass('o_kanban_hover'); @@ -122,6 +121,15 @@ var KanbanColumn = Widget.extend({ out: function () { self.$el.removeClass('o_kanban_hover'); }, + start: function (event, ui) { + ui.item.addClass('o_currently_dragged'); + }, + stop: function (event, ui) { + var item = ui.item; + setTimeout(function () { + item.removeClass('o_currently_dragged'); + }); + }, update: function (event, ui) { var record = ui.item.data('record'); var index = self.records.indexOf(record); 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 d9d7ac77fe2..46f6964dd1c 100644 --- a/addons/web/static/src/js/views/kanban/kanban_record.js +++ b/addons/web/static/src/js/views/kanban/kanban_record.js @@ -5,7 +5,6 @@ odoo.define('web.KanbanRecord', function (require) { * This file defines the KanbanRecord widget, which corresponds to a card in * a Kanban view. */ - var config = require('web.config'); var core = require('web.core'); var Domain = require('web.Domain'); @@ -210,6 +209,11 @@ var KanbanRecord = Widget.extend({ * @private */ _openRecord: function () { + if (this.$el.hasClass('o_currently_dragged')) { + // this record is currently being dragged and dropped, so we do not + // want to open it. + return; + } var editMode = this.$el.hasClass('oe_kanban_global_click_edit'); this.trigger_up('open_record', { id: this.db_id, 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 a4833b40d81..ac48ab769ff 100644 --- a/addons/web/static/src/js/views/pivot/pivot_controller.js +++ b/addons/web/static/src/js/views/pivot/pivot_controller.js @@ -345,7 +345,8 @@ var PivotController = AbstractController.extend({ var col_id = $target.data('id'); var measure = $target.data('measure'); var isAscending = $target.hasClass('o_pivot_measure_row_sorted_asc'); - this.model.sortRows(col_id, measure, isAscending); + var dataType = $target.data('data_type'); + this.model.sortRows(col_id, measure, isAscending, dataType); this.update({}, {reload: false}); }, /** diff --git a/addons/web/static/src/js/views/pivot/pivot_model.js b/addons/web/static/src/js/views/pivot/pivot_model.js index 1a0d3625440..5a6423fbe34 100644 --- a/addons/web/static/src/js/views/pivot/pivot_model.js +++ b/addons/web/static/src/js/views/pivot/pivot_model.js @@ -457,16 +457,23 @@ var PivotModel = AbstractModel.extend({ * @param {any} col_id * @param {any} measure * @param {any} descending + * @param {'data'|'comparisonData'|'variation'} [dataType] */ - sortRows: function (col_id, measure, descending) { + sortRows: function (col_id, measure, descending, dataType) { var cells = this.data.cells; + var comparisonFunction = compare; + if (this.data.compare) { + dataType = dataType || 'data'; + comparisonFunction = specialCompare; + } this._traverseTree(this.data.main_row.root, function (header) { - header.children.sort(compare); + header.children.sort(comparisonFunction); }); this.data.sorted_column = { id: col_id, measure: measure, order: descending ? 'desc' : 'asc', + dataType: dataType, }; function _getValue (id1, id2) { if ((id1 in cells) && (id2 in cells[id1])) { @@ -476,12 +483,26 @@ var PivotModel = AbstractModel.extend({ } function compare (row1, row2) { - var values1 = _getValue(row1.id, col_id), - values2 = _getValue(row2.id, col_id), - value1 = values1 ? values1[measure] : 0, - value2 = values2 ? values2[measure] : 0; + var values1 = _getValue(row1.id, col_id); + var values2 = _getValue(row2.id, col_id); + var value1 = values1 ? values1[measure] : 0; + var value2 = values2 ? values2[measure] : 0; return descending ? value1 - value2 : value2 - value1; } + function specialCompare (row1, row2) { + var values1 = _getValue(row1.id, col_id); + var values2 = _getValue(row2.id, col_id); + var value1 = values1 ? values1[measure] : {data: 0, comparisonData: 0, variation: {magnitude: 0}}; + var value2 = values2 ? values2[measure] : {data: 0, comparisonData: 0, variation: {magnitude: 0}}; + if (dataType === 'variation') { + return descending ? + value1[dataType].magnitude - value2[dataType].magnitude: + value2[dataType].magnitude - value1[dataType].magnitude; + } + return descending ? + value1[dataType] - value2[dataType]: + value2[dataType] - value1[dataType]; + } }, /** * Toggle the active state for a given measure, then reload the data. 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 a68d91330a9..787e28e38a9 100644 --- a/addons/web/static/src/js/views/pivot/pivot_renderer.js +++ b/addons/web/static/src/js/views/pivot/pivot_renderer.js @@ -116,6 +116,8 @@ var PivotRenderer = AbstractRenderer.extend({ _renderHeaders: function ($thead, headers, nbrCols) { var self = this; var i, j, cell, $row, $cell; + var measure, dataType; + var id, measureCellIds = []; var groupbyLabels = _.map(this.state.colGroupBys, function (gb) { return self.state.fields[gb.split(':')[0]].string; @@ -144,10 +146,13 @@ var PivotRenderer = AbstractRenderer.extend({ $cell.data('id', cell.id); } if (cell.measure) { + measure = cell.measure; + measureCellIds.push(cell.id); $cell.addClass('o_pivot_measure_row text-muted') - .text(this.state.fields[cell.measure].string); - $cell.data('id', cell.id).data('measure', cell.measure); - if (!this.compare && cell.id === this.state.sortedColumn.id && cell.measure === this.state.sortedColumn.measure) { + .text(this.state.fields[measure].string); + $cell.data('id', cell.id).data('measure', measure); + if (cell.id === this.state.sortedColumn.id && + measure === this.state.sortedColumn.measure) { $cell.addClass('o_pivot_measure_row_sorted_' + this.state.sortedColumn.order); if (this.state.sortedColumn.order == 'asc') { $cell.attr('aria-sorted', 'ascending'); @@ -167,12 +172,30 @@ var PivotRenderer = AbstractRenderer.extend({ } if (this.compare) { var colLabels = [this.timeRangeDescription, this.comparisonTimeRangeDescription, 'Variation']; + var dataTypes = ['data', 'comparisonData', 'variation']; $row = $('<tr>'); for (i = 0; i < 3 * nbrCols; i++) { + id = measureCellIds[~~(i / 3)]; + measure = this.state.measures[(~~(i / 3)) % this.state.measures.length]; + dataType = dataTypes[i % 3]; $cell = $('<th>') + .addClass('o_pivot_measure_row text-muted') + .data('data_type', dataType) + .data('id', id) + .data('measure', measure) .text(colLabels[i % 3]) .attr('rowspan', 1) .attr('colspan', 1); + if (dataType === this.state.sortedColumn.dataType && + id === this.state.sortedColumn.id && + measure === this.state.sortedColumn.measure) { + $cell.addClass('o_pivot_measure_row_sorted_' + this.state.sortedColumn.order); + if (this.state.sortedColumn.order === 'asc') { + $cell.attr('aria-sorted', 'ascending'); + } else { + $cell.attr('aria-sorted', 'descending'); + } + } $row.append($cell); } $thead.append($row); diff --git a/addons/web/static/src/js/widgets/attach_document.js b/addons/web/static/src/js/widgets/attach_document.js index 041b021d60b..13496f3aea7 100644 --- a/addons/web/static/src/js/widgets/attach_document.js +++ b/addons/web/static/src/js/widgets/attach_document.js @@ -11,7 +11,7 @@ var _t = core._t; var AttachDocument = Widget.extend({ template: 'AttachDocument', events: { - 'click span.o_attach_document': '_onClickAttachDocument', + 'click': '_onClickAttachDocument', 'change input.o_input_file': '_onFileChanged', }, /** @@ -76,6 +76,9 @@ var AttachDocument = Widget.extend({ * @param {Event} ev */ _onClickAttachDocument: function (ev) { + if ($(ev.target).is('input.o_input_file')) { + return; + } var fieldNames = this.getParent().canBeSaved(this.state.id); if (fieldNames.length) { return this._notifyInvalidFields(fieldNames); 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 c9498950a04..cc0f8825643 100644 --- a/addons/web/static/src/js/widgets/switch_company_menu.js +++ b/addons/web/static/src/js/widgets/switch_company_menu.js @@ -53,7 +53,7 @@ var SwitchCompanyMenu = Widget.extend({ } else { a = '<span style="margin-right: 24px;"/>'; } - companiesList += '<a href="#" class="dropdown-item" data-menu="company" data-company-id="' + + companiesList += '<a role="menuitem" href="#" class="dropdown-item" data-menu="company" data-company-id="' + company[0] + '">' + a + company[1] + '</a>'; }); this.$('.dropdown-menu').html(companiesList); diff --git a/addons/web/static/src/scss/bootstrap_overridden.scss b/addons/web/static/src/scss/bootstrap_overridden.scss index 09dd5ddbfd4..e8406c948e9 100644 --- a/addons/web/static/src/scss/bootstrap_overridden.scss +++ b/addons/web/static/src/scss/bootstrap_overridden.scss @@ -133,8 +133,8 @@ $modal-inner-padding: $o-horizontal-padding; // FIXME $modal-title-padding ? -$modal-lg: 980px; -$modal-md: 650px; +$modal-lg: $o-modal-lg; +$modal-md: $o-modal-md; // Breadcrumbs diff --git a/addons/web/static/src/scss/primary_variables.scss b/addons/web/static/src/scss/primary_variables.scss index 45d1b7ac807..2bdc03a132b 100644 --- a/addons/web/static/src/scss/primary_variables.scss +++ b/addons/web/static/src/scss/primary_variables.scss @@ -65,6 +65,9 @@ $o-sheet-vpadding: 24px; $o-notification-error-bg-color: #F16567; $o-notification-info-bg-color: #FCFBEA; +$o-modal-lg: 980px; +$o-modal-md: 650px; + // Needed for having no spacing between sheet and mail body in mass_mailing: // Different required cancel paddings between web and web_enterprise $o-sheet-cancel-tpadding: 0px; diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 102e70efa1e..55d744d3a60 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -235,7 +235,7 @@ <t t-name="WebClient.DebugManager"> <li class="o_debug_manager" role="menuitem"> - <a href="#" title="Open Developer Tools" aria-label="Open Developer Tools" data-toggle="dropdown" aria-expanded="false" tabindex="-1" data-display="static"> + <a role="button" href="#" title="Open Developer Tools" aria-label="Open Developer Tools" data-toggle="dropdown" aria-expanded="false" tabindex="-1" data-display="static"> <span class="fa fa-bug"/> </a> <div class="dropdown-menu dropdown-menu-right o_debug_dropdown" role="menu"/> @@ -853,7 +853,7 @@ <span class="o_badge_text" t-att-title="el.display_name"><span role="img" t-attf-aria-label="Tag color: #{colornames[color]}"/><t t-esc="el.display_name"/></span> </t> <t t-if="colorField"> - <a href="#" class="dropdown-toggle o-no-caret" data-toggle="dropdown"> + <a role="button" href="#" class="dropdown-toggle o-no-caret" data-toggle="dropdown" aria-expanded="false"> <t t-raw="_badge_text"/> </a> </t> @@ -1080,10 +1080,10 @@ <t t-if="widget.items.length !== 0"> <t t-set="group" t-value="0"/> <t t-foreach="widget.items" t-as="item"> - <div t-if="group !== item.groupNumber" class="dropdown-divider" data-removable="1"/> + <div t-if="group !== item.groupNumber" role="separator" class="dropdown-divider" data-removable="1"/> <div class="o_menu_item" t-att-data-id="item.id"> - <a href="#" t-attf-class="dropdown-item#{item.isActive ? ' selected ' : ''}"> + <a role="menuitem" href="#" t-attf-class="dropdown-item#{item.isActive ? ' selected ' : ''}"> <t t-esc="item.description"/> <span t-if="item.isRemovable" t-att-data-id="item.id" class="o_trash_button" > <span class="fa fa-trash-o"></span> </span> <span t-if="item.hasOptions" t-att-data-id="item.id" class="o_submenu_switcher"> @@ -1093,10 +1093,10 @@ <ul t-if="item.hasOptions && widget.openItems[item.id]" class="list-unstyled"> <t t-set="subgroup" t-value="0"/> <t t-foreach="item.options" t-as="option"> - <li t-if="subgroup !== option.groupNumber" class="dropdown-divider" data-removable="1"/> + <li t-if="subgroup !== option.groupNumber" role="separator" class="dropdown-divider" data-removable="1"/> <li class="o_item_option" t-att-data-item_id="item.id" t-att-data-option_id="option.optionId"> - <a href="#" t-attf-class="dropdown-item#{item.currentOptionId === option.optionId ? ' selected': ''} pl-5"><t t-esc="option.description"/></a> + <a role="menuitem" href="#" t-attf-class="dropdown-item#{item.currentOptionId === option.optionId ? ' selected': ''} pl-5"><t t-esc="option.description"/></a> </li> <t t-set="subgroup" t-value="option.groupNumber"/> </t> @@ -1117,8 +1117,8 @@ </div> <t t-name="GroupByMenuGenerator"> - <div t-if="widget.presentedFields.length !== 0 && widget.items.length !== 0" class="dropdown-divider o_generator_menu"/> - <button t-if="widget.presentedFields.length !== 0" type="button" class="dropdown-item o_generator_menu o_add_custom_group">Add Custom Group</button> + <div t-if="widget.presentedFields.length !== 0 && widget.items.length !== 0" role="separator" class="dropdown-divider o_generator_menu"/> + <button t-if="widget.presentedFields.length !== 0" type="button" class="dropdown-item o_generator_menu o_add_custom_group" aria-expanded="false">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"> @@ -1132,8 +1132,8 @@ </t> <t t-name="FilterMenuGenerator"> - <div t-if="Object.keys(widget.fields).length !== 0 && widget.items.length !== 0" class="dropdown-divider o_generator_menu"/> - <button t-if="Object.keys(widget.fields).length !== 0" type="button" class="dropdown-item o_generator_menu o_add_custom_filter">Add Custom Filter</button> + <div t-if="Object.keys(widget.fields).length !== 0 && widget.items.length !== 0" role="separator" class="dropdown-divider o_generator_menu"/> + <button t-if="Object.keys(widget.fields).length !== 0" type="button" class="dropdown-item o_generator_menu o_add_custom_filter" aria-expanded="false">Add Custom Filter</button> <div t-if="widget.generatorMenuIsOpen" class="dropdown-item-text o_generator_menu 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"> @@ -1335,7 +1335,7 @@ <label for="o_favorite_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 class="dropdown-item-text o_save_favorite"> - <button role="menuitem" type="button" class="btn btn-primary">Save</button> + <button type="button" class="btn btn-primary">Save</button> </div> </div> </div> @@ -1495,7 +1495,7 @@ <t t-name="UserMenu"> <li class="o_user_menu"> - <a class="dropdown-toggle" data-toggle="dropdown" data-display="static" aria-expanded="false" href="#"> + <a role="button" class="dropdown-toggle" data-toggle="dropdown" data-display="static" aria-expanded="false" href="#"> <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> @@ -1516,7 +1516,7 @@ <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"> + <a role="button" 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'}"/> </a> <div class="dropdown-menu dropdown-menu-right" role="menu"/> diff --git a/addons/web/static/src/xml/kanban.xml b/addons/web/static/src/xml/kanban.xml index b91b8844752..220395fef02 100644 --- a/addons/web/static/src/xml/kanban.xml +++ b/addons/web/static/src/xml/kanban.xml @@ -24,8 +24,8 @@ <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 and widget.archivable"> - <a href="#" class="dropdown-item o_column_archive_records">Archive All</a> - <a href="#" class="dropdown-item o_column_unarchive_records">Unarchive All</a> + <a role="menuitem" href="#" class="dropdown-item o_column_archive_records">Archive All</a> + <a role="menuitem" href="#" class="dropdown-item o_column_unarchive_records">Unarchive All</a> </t> </div> </span> diff --git a/addons/web/static/src/xml/menu.xml b/addons/web/static/src/xml/menu.xml index 4cf905674d7..3838cc6c226 100644 --- a/addons/web/static/src/xml/menu.xml +++ b/addons/web/static/src/xml/menu.xml @@ -97,7 +97,7 @@ <t t-extend="UserMenu.Actions"> <t t-jquery=".dropdown-divider" t-operation="before"> - <a href="#" data-menu="shortcuts" class="dropdown-item d-none d-md-inline-block">Shortcuts</a> + <a role="menuitem" href="#" data-menu="shortcuts" class="dropdown-item d-none d-md-inline-block">Shortcuts</a> </t> </t> |
