summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-01-09 19:59:27 +0100
committerChristophe Simonis <chs@odoo.com>2019-01-09 19:59:27 +0100
commitd7c5bc02cc2b27442f0d4c8aca70266762be2a32 (patch)
tree3a675d15b539a4474be38704405b318bebecdce7 /addons/web/static/src/js/views
parent37b518f1749aff3d6ffb2246c32f2aa1e67d9067 (diff)
parent8aa8548d8ab68feb13f3bde51c557db84877e809 (diff)
[MERGE] forward port branch saas-12.1 up to 8aa8548d8ab
Diffstat (limited to 'addons/web/static/src/js/views')
-rw-r--r--addons/web/static/src/js/views/abstract_view.js2
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js38
-rw-r--r--addons/web/static/src/js/views/basic/basic_view.js15
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_model.js15
-rw-r--r--addons/web/static/src/js/views/control_panel/control_panel_controller.js9
-rw-r--r--addons/web/static/src/js/views/control_panel/control_panel_model.js5
-rw-r--r--addons/web/static/src/js/views/control_panel/control_panel_renderer.js2
-rw-r--r--addons/web/static/src/js/views/control_panel/control_panel_view.js2
-rw-r--r--addons/web/static/src/js/views/form/form_view.js18
-rw-r--r--addons/web/static/src/js/views/graph/graph_renderer.js9
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_column.js10
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_record.js6
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_renderer_mobile.js3
-rw-r--r--addons/web/static/src/js/views/list/list_view.js15
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_controller.js3
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_model.js33
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_renderer.js29
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_view.js8
18 files changed, 169 insertions, 53 deletions
diff --git a/addons/web/static/src/js/views/abstract_view.js b/addons/web/static/src/js/views/abstract_view.js
index 75de2be9446..5921c1b4bc3 100644
--- a/addons/web/static/src/js/views/abstract_view.js
+++ b/addons/web/static/src/js/views/abstract_view.js
@@ -105,7 +105,7 @@ var AbstractView = Factory.extend({
this.arch = this.fieldsView.arch;
this.fields = this.fieldsView.viewFields;
this.userContext = params.userContext || {};
- this.withControlPanel = params.withControlPanel;
+ this.withControlPanel = this.withControlPanel && params.withControlPanel;
// the boolean parameter 'isEmbedded' determines if the view should be
// considered as a subview. For now this is only used by the graph
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 8266b1dee42..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,
@@ -4289,9 +4289,12 @@ var BasicModel = AbstractModel.extend({
}
return list;
}).then(function () {
- self._fetchX2ManysSingleBatch(list);
- self._fetchReferencesSingleBatch(list);
- return list;
+ var fetchingDefs = [];
+ fetchingDefs.push(self._fetchX2ManysSingleBatch(list));
+ fetchingDefs.push(self._fetchReferencesSingleBatch(list));
+ return $.when.apply($, fetchingDefs).then(function () {
+ return list;
+ });
});
});
},
@@ -4322,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/control_panel/control_panel_controller.js b/addons/web/static/src/js/views/control_panel/control_panel_controller.js
index 991cee949e8..3d6e62f4bf9 100644
--- a/addons/web/static/src/js/views/control_panel/control_panel_controller.js
+++ b/addons/web/static/src/js/views/control_panel/control_panel_controller.js
@@ -160,12 +160,11 @@ var ControlPanelController = mvc.Controller.extend({
*/
_onFacetRemoved: function (ev) {
ev.stopPropagation();
- var group = ev.data.group;
- if (!group) {
- group = this.renderer.getLastFacet();
+ var group = ev.data.group || this.renderer.getLastFacet();
+ if (group) {
+ this.model.deactivateGroup(group.id);
+ this._reportNewQueryAndRender();
}
- this.model.deactivateGroup(group.id);
- this._reportNewQueryAndRender();
},
/**
* @private
diff --git a/addons/web/static/src/js/views/control_panel/control_panel_model.js b/addons/web/static/src/js/views/control_panel/control_panel_model.js
index 9353022eacf..67b1a4c64f8 100644
--- a/addons/web/static/src/js/views/control_panel/control_panel_model.js
+++ b/addons/web/static/src/js/views/control_panel/control_panel_model.js
@@ -645,10 +645,7 @@ var ControlPanelModel = mvc.Model.extend({
* @returns {Object} context
*/
_getFilterContext: function (filter) {
- var context = {};
- if (filter.type === 'favorite') {
- _.extend(context, filter.context);
- }
+ var context = filter.context || {};
// the following code aims to restore this:
// https://github.com/odoo/odoo/blob/master/addons/web/static/src/js/views/search/search_inputs.js#L498
// this is required for the helpdesk tour to pass
diff --git a/addons/web/static/src/js/views/control_panel/control_panel_renderer.js b/addons/web/static/src/js/views/control_panel/control_panel_renderer.js
index eea7fdae430..665fe73bf7d 100644
--- a/addons/web/static/src/js/views/control_panel/control_panel_renderer.js
+++ b/addons/web/static/src/js/views/control_panel/control_panel_renderer.js
@@ -102,7 +102,7 @@ var ControlPanelRenderer = Renderer.extend({
//--------------------------------------------------------------------------
/**
- * @returns {Object}
+ * @returns {Object|undefined}
*/
getLastFacet: function () {
return this.state.facets.slice(-1)[0];
diff --git a/addons/web/static/src/js/views/control_panel/control_panel_view.js b/addons/web/static/src/js/views/control_panel/control_panel_view.js
index 381e5dcf7e5..2bde26340e7 100644
--- a/addons/web/static/src/js/views/control_panel/control_panel_view.js
+++ b/addons/web/static/src/js/views/control_panel/control_panel_view.js
@@ -141,6 +141,7 @@ var ControlPanelView = Factory.extend({
'Ω';
if (filter.type === 'filter') {
filter.domain = attrs.domain;
+ filter.context = pyUtils.eval('context', attrs.context);
if (attrs.date) {
filter.fieldName = attrs.date;
filter.fieldType = this.fields[attrs.date].type;
@@ -196,6 +197,7 @@ var ControlPanelView = Factory.extend({
var groupOfGroupBys = [];
var groupNumber = 1;
+
_.each(preFilters, function (preFilter) {
if (preFilter.attrs && preFilter.attrs.invisible) {
return;
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 d49f2b005fa..5a00350c68f 100644
--- a/addons/web/static/src/js/views/form/form_view.js
+++ b/addons/web/static/src/js/views/form/form_view.js
@@ -26,13 +26,20 @@ var FormView = BasicView.extend({
* @override
*/
init: function (viewInfo, params) {
+ var hasSidebar = params.hasSidebar;
this._super.apply(this, arguments);
var mode = params.mode || (params.currentId ? 'readonly' : 'edit');
this.loadParams.type = 'record';
+ // this is kind of strange, but the param object is modified by
+ // AbstractView, so we only need to use its hasSidebar value if it was
+ // not already present in the beginning of this method
+ if (hasSidebar === undefined) {
+ hasSidebar = params.hasSidebar;
+ }
+ this.controllerParams.hasSidebar = hasSidebar;
this.controllerParams.disableAutofocus = params.disable_autofocus;
- this.controllerParams.hasSidebar = params.hasSidebar;
this.controllerParams.toolbarActions = viewInfo.toolbar;
this.controllerParams.footerToButtons = params.footerToButtons;
@@ -63,7 +70,6 @@ var FormView = BasicView.extend({
/**
* @override
- * @param {string} [action.target]
*/
_extractParamsFromAction: function (action) {
var params = this._super.apply(this, arguments);
@@ -73,6 +79,7 @@ var FormView = BasicView.extend({
params.withControlPanel = !(inDialog || inline);
params.footerToButtons = inDialog;
params.hasSearchView = inDialog ? false : params.hasSearchView;
+ params.hasSidebar = !inDialog && !inline;
params.searchMenuTypes = inDialog ? [] : params.searchMenuTypes;
if (inDialog || inline || fullscreen) {
params.mode = 'edit';
@@ -115,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/graph/graph_renderer.js b/addons/web/static/src/js/views/graph/graph_renderer.js
index fe4efab1b20..38c2f02351e 100644
--- a/addons/web/static/src/js/views/graph/graph_renderer.js
+++ b/addons/web/static/src/js/views/graph/graph_renderer.js
@@ -337,8 +337,8 @@ return AbstractRenderer.extend({
var self = this;
// Remove Undefined of first GroupBy
- var graphData = _.filter(this.state.data, function(elem){
- return elem.labels[0] !== undefined;
+ var graphData = _.filter(this.state.data, function (elem) {
+ return elem.labels[0] !== undefined && elem.labels[0] !== _t("Undefined");
});
// undefined label value becomes a string 'Undefined' translated
@@ -391,10 +391,9 @@ return AbstractRenderer.extend({
var tick = 0;
var serie, tickLabel;
var identity = function (p) {return p;};
-
- for (var i = 0; i < this.state.data.length; i++) {
+ for (var i = 0; i < graphData.length; i++) {
if (graphData[i].labels[0] !== tickLabel) {
- tickLabel = this.state.data[i].labels[0];
+ tickLabel = graphData[i].labels[0];
ticksLabels.push(tickLabel);
tick++;
}
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/kanban/kanban_renderer_mobile.js b/addons/web/static/src/js/views/kanban/kanban_renderer_mobile.js
index 8619448e793..b7f2dd62b28 100644
--- a/addons/web/static/src/js/views/kanban/kanban_renderer_mobile.js
+++ b/addons/web/static/src/js/views/kanban/kanban_renderer_mobile.js
@@ -143,7 +143,7 @@ KanbanRenderer.include({
onSuccess: function () {
// update the columns and tabs positions (optionally with an animation)
var updateFunc = animate ? 'animate' : 'css';
- self.$('.o_kanban_mobile_tab').removeClass('o_current');
+ self.$('.o_kanban_mobile_tab, .o_kanban_group').removeClass('o_current');
_.each(self.widgets, function (column, index) {
var columnID = column.id || column.db_id;
var $column = self.$('.o_kanban_group[data-id="' + columnID + '"]');
@@ -157,6 +157,7 @@ KanbanRenderer.include({
} else if (index === moveToIndex) {
$column[updateFunc]({left: '0%'});
$tab[updateFunc]({left: '50%'});
+ $column.addClass('o_current');
$tab.addClass('o_current');
} else if (index < moveToIndex) {
$column.css({left: '-100%'});
diff --git a/addons/web/static/src/js/views/list/list_view.js b/addons/web/static/src/js/views/list/list_view.js
index 291cb8de8a0..a28eb4da03a 100644
--- a/addons/web/static/src/js/views/list/list_view.js
+++ b/addons/web/static/src/js/views/list/list_view.js
@@ -57,8 +57,21 @@ var ListView = BasicView.extend({
//--------------------------------------------------------------------------
// Private
- //---
+ //--------------------------------------------------------------------------
+ /**
+ * @override
+ */
+ _extractParamsFromAction: function (action) {
+ var params = this._super.apply(this, arguments);
+ var inDialog = action.target === 'new';
+ var inline = action.target === 'inline';
+ params.hasSidebar = !inDialog && !inline;
+ return params;
+ },
+ /**
+ * @override
+ */
_updateMVCParams: function () {
this._super.apply(this, arguments);
this.controllerParams.noLeaf = !!this.loadParams.context.group_by_no_leaf;
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/views/pivot/pivot_view.js b/addons/web/static/src/js/views/pivot/pivot_view.js
index 38d8d80a9d7..5e05a2fe7e7 100644
--- a/addons/web/static/src/js/views/pivot/pivot_view.js
+++ b/addons/web/static/src/js/views/pivot/pivot_view.js
@@ -70,9 +70,6 @@ var PivotView = AbstractView.extend({
widgets[name] = field.attrs.widget;
}
- if (field.attrs.string) {
- measures[name].string = field.attrs.string;
- }
if (field.attrs.invisible && py.eval(field.attrs.invisible)) {
delete measures[name];
@@ -89,6 +86,11 @@ var PivotView = AbstractView.extend({
if (field.attrs.type === 'measure' && !(field.attrs.name in measures)) {
measures[field.attrs.name] = self.fields[field.attrs.name];
}
+
+ if (field.attrs.string) {
+ measures[name].string = field.attrs.string;
+ }
+
if (field.attrs.type === 'measure' || 'operator' in field.attrs) {
activeMeasures.push(name);
measures[name] = self.fields[name];