summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2017-10-25 14:57:24 +0200
committerChristophe Simonis <chs@odoo.com>2017-10-25 14:57:24 +0200
commit693f8dc68add34663f798370b4aea305f573f16d (patch)
treedbd47871d9412317dc96fd4ba349196badab199c /addons/web/static/src
parentc7a6409fac80a2d33006ab56fe40d27f2acd2cfd (diff)
parent7bfde6e05d12be959d04f4842237bfcc05f3c93f (diff)
[MERGE] forward port branch saas-16 up to 7bfde6e05d1
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/fields/abstract_field.js3
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js2
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js16
-rw-r--r--addons/web/static/src/js/views/basic/basic_controller.js6
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js8
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_controller.js6
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_model.js21
-rw-r--r--addons/web/static/src/js/views/field_manager_mixin.js2
-rw-r--r--addons/web/static/src/js/views/form/form_renderer.js4
-rw-r--r--addons/web/static/src/js/views/list/list_editable_renderer.js22
-rw-r--r--addons/web/static/src/js/views/list/list_renderer.js14
-rw-r--r--addons/web/static/src/less/form_view.less1
-rw-r--r--addons/web/static/src/less/list_view.less8
13 files changed, 88 insertions, 25 deletions
diff --git a/addons/web/static/src/js/fields/abstract_field.js b/addons/web/static/src/js/fields/abstract_field.js
index cef45c2a976..fc29ba77466 100644
--- a/addons/web/static/src/js/fields/abstract_field.js
+++ b/addons/web/static/src/js/fields/abstract_field.js
@@ -391,6 +391,8 @@ var AbstractField = Widget.extend({
* Please do not use this flag unless you really need it. Our only use
* case is currently the pad widget, which does a _setValue in the
* renderEdit method.
+ * @param {boolean} [options.notifyChange=true] if false, the basic model
+ * will not notify and not trigger the onchange, even though it was changed.
* @param {boolean} [options.forceChange=false] if true, the change event will be
* triggered even if the new value is the same as the old one
* @returns {Deferred}
@@ -421,6 +423,7 @@ var AbstractField = Widget.extend({
changes: changes,
viewType: this.viewType,
doNotSetDirty: options && options.doNotSetDirty,
+ notifyChange: !options || options.notifyChange !== false,
onSuccess: def.resolve.bind(def),
onFailure: def.reject.bind(def),
});
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index 8eae8f5b8f1..549b2e256be 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -205,7 +205,7 @@ var InputField = DebouncedField.extend({
if (!event || event === this.lastChangeEvent) {
this.isDirty = false;
}
- if (this.isDirty || (event && event.target === this)) {
+ if (this.isDirty || (event && event.target === this && event.data.changes[this.name] === this.value)) {
return $.when();
} else {
return this._render();
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index c4422285ae7..f2cacb3327f 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -1033,13 +1033,25 @@ var FieldX2Many = AbstractField.extend({
*/
_onResequence: function (event) {
var self = this;
- _.each(event.data.rowIDs, function (rowID, index) {
+ var rowIDs = event.data.rowIDs.slice();
+ var rowID = rowIDs.pop();
+ var defs = _.map(rowIDs, function (rowID, index) {
var data = {};
data[event.data.handleField] = event.data.offset + index;
- self._setValue({
+ return self._setValue({
operation: 'UPDATE',
id: rowID,
data: data,
+ }, {
+ notifyChange: false,
+ });
+ });
+ $.when.apply($, defs).then(function () {
+ // trigger only once the onchange for parent record
+ self._setValue({
+ operation: 'UPDATE',
+ id: rowID,
+ data: _.object([event.data.handleField], [event.data.offset + rowIDs.length]),
});
});
},
diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js
index c899530de07..5fc68e3124e 100644
--- a/addons/web/static/src/js/views/basic/basic_controller.js
+++ b/addons/web/static/src/js/views/basic/basic_controller.js
@@ -447,7 +447,11 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
*/
_setMode: function (mode, recordID) {
if ((recordID || this.handle) === this.handle) {
- return this.update({mode: mode}, {reload: false});
+ return this.update({mode: mode}, {reload: false}).then(function () {
+ // necessary to allow all sub widgets to use their dimensions in
+ // layout related activities, such as autoresize on fieldtexts
+ core.bus.trigger('DOM_updated');
+ });
}
return $.when();
},
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 1df118ecfd9..f3b23bdab7a 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -1092,6 +1092,9 @@ var BasicModel = AbstractModel.extend({
* @param {boolean} [options.doNotSetDirty=false] if this flag is set to
* true, then we will not tag the record as dirty. This should be avoided
* for most situations.
+ * @param {boolean} [options.notifyChange=true] if this flag is set to
+ * false, then we will not notify and not trigger the onchange, even though
+ * it was changed.
* @param {string} [options.viewType] current viewType. If not set, we will assume
* main viewType from the record
* @returns {Deferred}
@@ -1119,6 +1122,10 @@ var BasicModel = AbstractModel.extend({
}
}
+ if (options.notifyChange === false) {
+ return $.when();
+ }
+
return $.when.apply($, defs).then(function () {
var onChangeFields = []; // the fields that have changed and that have an on_change
for (var fieldName in changes) {
@@ -2305,6 +2312,7 @@ var BasicModel = AbstractModel.extend({
var ids = record.data[fieldName] || [];
var list = self._makeDataPoint({
count: ids.length,
+ context: record.context,
fieldsInfo: fieldsInfo,
fields: view ? view.fields : fieldInfo.relatedFields,
limit: fieldInfo.limit,
diff --git a/addons/web/static/src/js/views/calendar/calendar_controller.js b/addons/web/static/src/js/views/calendar/calendar_controller.js
index 08d03c037f0..f76f40460a1 100644
--- a/addons/web/static/src/js/views/calendar/calendar_controller.js
+++ b/addons/web/static/src/js/views/calendar/calendar_controller.js
@@ -56,7 +56,6 @@ var CalendarController = AbstractController.extend({
// Public
//--------------------------------------------------------------------------
-
/**
* Render the buttons according to the CalendarView.buttons template and
* add listeners on it. Set this.$buttons with the produced jQuery element
@@ -160,10 +159,10 @@ var CalendarController = AbstractController.extend({
}
this.quickCreating = true;
this.model.createRecord(event)
- .then(function (id) {
+ .then(function () {
self.quick.destroy();
self.quick = null;
- self.reload(id);
+ self.reload();
})
.fail(function (error, errorEvent) {
// This will occurs if there are some more fields required
@@ -215,7 +214,6 @@ var CalendarController = AbstractController.extend({
if(!options.disableQuickCreate && !event.data.disableQuickCreate && this.quickAddPop) {
this.quick = new QuickCreate(this, true, options, data, event.data);
- this.quick.on('added', this, this.reload.bind(this));
this.quick.open();
this.quick.focus();
return;
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 4374421d7b3..b32374057bb 100644
--- a/addons/web/static/src/js/views/calendar/calendar_model.js
+++ b/addons/web/static/src/js/views/calendar/calendar_model.js
@@ -322,6 +322,7 @@ return AbstractModel.extend({
// List authorized values for every field
// fields with an active 'all' filter are skipped
var authorizedValues = {};
+ var avoidValues = {};
_.each(this.data.filters, function (filter) {
// Skip 'all' filters because they do not affect the domain
@@ -329,11 +330,20 @@ return AbstractModel.extend({
// Loop over subfilters to complete authorizedValues
_.each(filter.filters, function (f) {
- if (!authorizedValues[filter.fieldName])
- authorizedValues[filter.fieldName] = [];
+ if (filter.write_model) {
+ if (!authorizedValues[filter.fieldName])
+ authorizedValues[filter.fieldName] = [];
+
+ if (f.active) {
+ authorizedValues[filter.fieldName].push(f.value);
+ }
+ } else {
+ if (!avoidValues[filter.fieldName])
+ avoidValues[filter.fieldName] = [];
- if (f.active) {
- authorizedValues[filter.fieldName].push(f.value);
+ if (!f.active) {
+ avoidValues[filter.fieldName].push(f.value);
+ }
}
});
});
@@ -343,6 +353,9 @@ return AbstractModel.extend({
for (var field in authorizedValues) {
domain.push([field, 'in', authorizedValues[field]]);
}
+ for (var field in avoidValues) {
+ domain.push([field, 'not in', avoidValues[field]]);
+ }
return domain;
},
diff --git a/addons/web/static/src/js/views/field_manager_mixin.js b/addons/web/static/src/js/views/field_manager_mixin.js
index aaf7e4a5859..2909308cf29 100644
--- a/addons/web/static/src/js/views/field_manager_mixin.js
+++ b/addons/web/static/src/js/views/field_manager_mixin.js
@@ -46,7 +46,7 @@ var FieldManagerMixin = {
*/
_applyChanges: function (dataPointID, changes, event) {
var self = this;
- var options = _.pick(event.data, 'viewType', 'doNotSetDirty');
+ var options = _.pick(event.data, 'viewType', 'doNotSetDirty', 'notifyChange');
return this.model.notifyChanges(dataPointID, changes, options)
.then(function (result) {
if (event.data.force_save) {
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 5224a6c149a..7e18849af3f 100644
--- a/addons/web/static/src/js/views/form/form_renderer.js
+++ b/addons/web/static/src/js/views/form/form_renderer.js
@@ -800,10 +800,6 @@ var FormRenderer = BasicRenderer.extend({
this.$el.toggleClass('o_form_editable', this.mode === 'edit');
this.$el.toggleClass('o_form_readonly', this.mode === 'readonly');
- // Necessary to allow all sub widgets to use their dimensions in
- // layout related activities, such as autoresize on fieldtexts
- core.bus.trigger('DOM_updated');
-
// Attach the tooltips on the fields' label
_.each(this.allFieldWidgets[this.state.id], function (widget) {
var idForLabel = self.idsForLabels[widget.name];
diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js
index b0ddbdcd385..c1ef23b6b5e 100644
--- a/addons/web/static/src/js/views/list/list_editable_renderer.js
+++ b/addons/web/static/src/js/views/list/list_editable_renderer.js
@@ -101,6 +101,7 @@ ListRenderer.include({
});
var $row = self.$('.o_data_row:nth(' + rowIndex + ')');
self._setDecorationClasses(state.data[rowIndex], $row);
+ self._updateFooter();
}
return widgets;
});
@@ -542,12 +543,21 @@ ListRenderer.include({
_resequence: function (event, ui) {
var self = this;
var movedRecordID = ui.item.data('id');
- var rowIDs = _.pluck(this.state.data, 'id');
- rowIDs = _.without(rowIDs, movedRecordID);
- rowIDs.splice(ui.item.index(), 0, movedRecordID);
- var sequences = _.map(this.state.data, function(record) {
- return record.data[self.handleField];
- });
+ var rows = this.state.data;
+ var row = _.findWhere(rows, {id: movedRecordID});
+ var index0 = rows.indexOf(row);
+ var index1 = ui.item.index();
+ rows = rows.slice(Math.min(index0, index1), Math.max(index0, index1) + 1);
+ rows = _.without(rows, row);
+ if (index0 > index1) {
+ rows.unshift(row);
+ } else {
+ rows.push(row);
+ }
+
+ var sequences = _.pluck(_.pluck(rows, 'data'), self.handleField);
+ var rowIDs = _.pluck(rows, 'id');
+
this.trigger_up('resequence', {
rowIDs: rowIDs,
offset: _.min(sequences),
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 d37120339d6..8b24d265be8 100644
--- a/addons/web/static/src/js/views/list/list_renderer.js
+++ b/addons/web/static/src/js/views/list/list_renderer.js
@@ -682,6 +682,17 @@ var ListRenderer = BasicRenderer.extend({
});
},
/**
+ * Update the footer aggregate values. This method should be called each
+ * time the state of some field is changed, to make sure their sum are kept
+ * in sync.
+ *
+ * @private
+ */
+ _updateFooter: function () {
+ this._computeAggregates();
+ this.$('tfoot').replaceWith(this._renderFooter(!!this.state.groupedBy.length));
+ },
+ /**
* Whenever we change the state of the selected rows, we need to call this
* method to keep the this.selection variable in sync, and also to recompute
* the aggregates.
@@ -695,8 +706,7 @@ var ListRenderer = BasicRenderer.extend({
return $(row).data('id');
});
this.trigger_up('selection_changed', { selection: this.selection });
- this._computeAggregates();
- this.$('tfoot').replaceWith(this._renderFooter(!!this.state.groupedBy.length));
+ this._updateFooter();
},
//--------------------------------------------------------------------------
diff --git a/addons/web/static/src/less/form_view.less b/addons/web/static/src/less/form_view.less
index 9bfbd6c535e..cd9d550843a 100644
--- a/addons/web/static/src/less/form_view.less
+++ b/addons/web/static/src/less/form_view.less
@@ -203,6 +203,7 @@
&.disabled {
opacity: 1.0;
color: @text-muted;
+ pointer-events: none;
border-left: 1px solid @gray-lighter-dark;
}
diff --git a/addons/web/static/src/less/list_view.less b/addons/web/static/src/less/list_view.less
index 82debf1a035..395bf633e45 100644
--- a/addons/web/static/src/less/list_view.less
+++ b/addons/web/static/src/less/list_view.less
@@ -138,6 +138,14 @@
// consider this later if needed.
z-index: 1;
+ // The in-edition elements will overflow other elements (the rows below,
+ // the content below the list view, ...). As those might be using
+ // position: relative, the in-edition elements have to define a z-index.
+ // Technically, creating a stacking context for a meaningful parent
+ // (maybe the .o_content) might be required for safety but we should
+ // consider this later if needed.
+ z-index: 1;
+
// Field widgets override
> .o_field_widget {
.o-position-absolute(0, 0, auto, 0);