diff options
| author | Christophe Simonis <chs@odoo.com> | 2017-11-28 15:12:31 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2017-11-28 15:12:31 +0100 |
| commit | 5851a69aa3ac2b140ffccdbe43427cdad3e74e0c (patch) | |
| tree | 2da1f6c4d65f4466bc8c263328ae55b007ca6da7 /addons/web/static/src | |
| parent | 41d2470093a5e18ecebc86f2f878813f1879462d (diff) | |
| parent | 3f66814a0d01a81bef5456a07da4b1ac8e2281e7 (diff) | |
[MERGE] forward port branch saas-16 up to 3f66814a0d0
Diffstat (limited to 'addons/web/static/src')
12 files changed, 76 insertions, 31 deletions
diff --git a/addons/web/static/src/js/chrome/search_filters.js b/addons/web/static/src/js/chrome/search_filters.js index b9cf1b0fce9..e2eff03546d 100644 --- a/addons/web/static/src/js/chrome/search_filters.js +++ b/addons/web/static/src/js/chrome/search_filters.js @@ -187,7 +187,10 @@ var DateTime = Field.extend({ {value: "∄", text: _lt("is not set")} ], get_value: function (index) { - return this["datewidget_" + (index || 0)].getValue(); + // retrieve the datepicker value + var value = this["datewidget_" + (index || 0)].getValue(); + // convert to utc + return value.add(-this.getSession().getTZOffset(value), 'minutes'); }, get_domain: function (field, operator) { switch (operator.value) { diff --git a/addons/web/static/src/js/core/rpc.js b/addons/web/static/src/js/core/rpc.js index 6ad91c0e4f9..53d298c9019 100644 --- a/addons/web/static/src/js/core/rpc.js +++ b/addons/web/static/src/js/core/rpc.js @@ -51,9 +51,15 @@ return { } if (options.method === 'read_group') { - params.kwargs.domain = options.domain || params.domain || params.kwargs.domain || []; - params.kwargs.fields = options.fields || params.fields || params.kwargs.fields || []; - params.kwargs.groupby = options.groupBy || params.groupBy || params.kwargs.groupby || []; + if (!(params.args && params.args[0] !== undefined)) { + params.kwargs.domain = options.domain || params.domain || params.kwargs.domain || []; + } + if (!(params.args && params.args[1] !== undefined)) { + params.kwargs.fields = options.fields || params.fields || params.kwargs.fields || []; + } + if (!(params.args && params.args[2] !== undefined)) { + params.kwargs.groupby = options.groupBy || params.groupBy || params.kwargs.groupby || []; + } params.kwargs.offset = options.offset || params.offset || params.kwargs.offset; params.kwargs.limit = options.limit || params.limit || params.kwargs.limit; // In kwargs, we look for "orderby" rather than "orderBy" (note the absence of capital B), diff --git a/addons/web/static/src/js/services/data_manager.js b/addons/web/static/src/js/services/data_manager.js index e99f9ebb6f2..501961d6d76 100644 --- a/addons/web/static/src/js/services/data_manager.js +++ b/addons/web/static/src/js/services/data_manager.js @@ -423,8 +423,12 @@ return core.Class.extend({ if (fieldsInfo[node.attrs.name].fieldDependencies) { var deps = fieldsInfo[node.attrs.name].fieldDependencies; for (var dependency_name in deps) { + var dependency_dict = {name: dependency_name, type: deps[dependency_name].type}; if (!(dependency_name in fieldsInfo)) { - fieldsInfo[dependency_name] = {'name': dependency_name, 'type': deps[dependency_name].type, 'options': deps[dependency_name].options || {}}; + fieldsInfo[dependency_name] = _.extend({}, dependency_dict, {options: deps[dependency_name].options || {}}); + } + if (!(dependency_name in fields)) { + fields[dependency_name] = dependency_dict; } } } diff --git a/addons/web/static/src/js/views/abstract_view.js b/addons/web/static/src/js/views/abstract_view.js index a6cfea6e3be..6cc8a3c8143 100644 --- a/addons/web/static/src/js/views/abstract_view.js +++ b/addons/web/static/src/js/views/abstract_view.js @@ -226,9 +226,6 @@ var AbstractView = Class.extend({ return; } - attrs.limit = attrs.mode === "tree" ? 80 : - (attrs.widget === 'many2many_tags' ? 1000 : 40); - if (attrs.Widget.prototype.useSubview && !attrs.__no_fetch && !attrs.views[attrs.mode]) { var context = {}; var regex = /'([a-z]*_view_ref)' *: *'(.*?)'/g; @@ -244,12 +241,30 @@ var AbstractView = Class.extend({ for (var viewName in views) { attrs.views[viewName] = views[viewName]; } + self._setSubViewLimit(attrs); })); + } else { + self._setSubViewLimit(attrs); } }); } return $.when.apply($, defs); - } + }, + /** + * We set here the limit for the number of records fetched (in one page). + * This method is only called for subviews, not for main views. + * + * @private + * @param {Object} attrs + */ + _setSubViewLimit: function (attrs) { + var view = attrs.views && attrs.views[attrs.mode]; + var limit = view && view.arch.attrs.limit && parseInt(view.arch.attrs.limit); + if (!limit && attrs.widget === 'many2many_tags') { + limit = 1000; + } + attrs.limit = limit || 40; + }, }); return AbstractView; 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 4bd12bf2bc3..c16f635a604 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1588,7 +1588,9 @@ var BasicModel = AbstractModel.extend({ return $.when.apply($, defs).then(function () { // ensure to fetch up to 'limit' records (may be useful if records of // the current page have been removed) - return self._readUngroupedList(list); + return self._readUngroupedList(list).then(function () { + return self._fetchX2ManysBatched(list); + }); }); }, /** @@ -2516,6 +2518,8 @@ var BasicModel = AbstractModel.extend({ changes[fieldName] = value ? this.localData[value].model + ',' + this.localData[value].res_id : false; + } else if (type === 'char' && changes[fieldName] === '') { + changes[fieldName] = false; } else if (changes[fieldName] === null) { changes[fieldName] = false; } 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 543ce01191e..21fabbc2274 100644 --- a/addons/web/static/src/js/views/basic/basic_renderer.js +++ b/addons/web/static/src/js/views/basic/basic_renderer.js @@ -357,6 +357,17 @@ var BasicRenderer = AbstractRenderer.extend({ return this.state.count !== 0; }, /** + * This function is called each time a field widget is created, when it is + * ready (after its willStart and Start methods are complete). This is the + * place where work having to do with $el should be done. + * + * @private + * @param {Widget} widget the field widget instance + * @param {Object} node the attrs coming from the arch + */ + _postProcessField: function (widget, node) { + }, + /** * Registers or updates the modifiers data associated to the given node. * This method is quiet complex as it handles all the needs of the basic * renderers: @@ -524,6 +535,7 @@ var BasicRenderer = AbstractRenderer.extend({ )); }, }, modifiersOptions || {})); + self._postProcessField(widget, node); }); return widget; diff --git a/addons/web/static/src/js/views/form/form_controller.js b/addons/web/static/src/js/views/form/form_controller.js index 7b53b60f90c..88e8a99de53 100644 --- a/addons/web/static/src/js/views/form/form_controller.js +++ b/addons/web/static/src/js/views/form/form_controller.js @@ -485,6 +485,7 @@ var FormController = BasicController.extend({ * @param {OdooEvent} event */ _onOpenRecord: function (event) { + event.stopPropagation(); var self = this; var record = this.model.get(event.data.id, {raw: true}); new dialogs.FormViewDialog(self, { 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 55c23b5d3a2..e18615c8caf 100644 --- a/addons/web/static/src/js/views/form/form_renderer.js +++ b/addons/web/static/src/js/views/form/form_renderer.js @@ -247,6 +247,17 @@ var FormRenderer = BasicRenderer.extend({ return idForLabel; }, /** + * @override + * @private + */ + _postProcessField: function (widget, node) { + this._setIDForLabel(widget, this._getIDForLabel(node.attrs.name)); + this._handleAttributes(widget.$el, node); + if (JSON.parse(node.attrs.default_focus || "0")) { + this.defaultFocusField = widget; + } + }, + /** * @private * @param {Object} node * @returns {jQueryElement} @@ -308,23 +319,6 @@ var FormRenderer = BasicRenderer.extend({ return $result; }, /** - * @override - * @private - * @param {string} node - * @param {Object} record - * @param {Object} [options] - * @returns {AbstractField} - */ - _renderFieldWidget: function (node, record, options, modifiersOptions) { - var widget = this._super.apply(this, arguments); - this._setIDForLabel(widget, this._getIDForLabel(node.attrs.name)); - this._handleAttributes(widget.$el, node); - if (JSON.parse(node.attrs.default_focus || "0")) { - this.defaultFocusField = widget; - } - return widget; - }, - /** * @private * @param {Object} node * @returns {jQueryElement} 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 907d312365d..d39a3b280e1 100644 --- a/addons/web/static/src/js/views/kanban/kanban_column.js +++ b/addons/web/static/src/js/views/kanban/kanban_column.js @@ -52,7 +52,7 @@ var KanbanColumn = Widget.extend({ this.grouped_by_m2o = options.grouped_by_m2o; this.editable = options.editable; this.deletable = options.deletable; - this.draggable = recordOptions.draggable; + this.draggable = options.draggable; this.records_editable = options.records_editable; this.records_deletable = options.records_deletable; this.relation = options.relation; @@ -97,12 +97,13 @@ var KanbanColumn = Widget.extend({ } this.$header.find('.o_kanban_header_title').tooltip(); - if (!config.device.isMobile && this.draggable !== false) { + if (!config.device.isMobile) { // deactivate sortable in mobile mode. It does not work anyway, // and it breaks horizontal scrolling in kanban views. Someday, we // should find a way to use the touch events to make sortable work. this.$el.sortable({ connectWith: '.o_kanban_group', + containment: this.draggable ? '.o_kanban_view' : 'parent', revert: 0, delay: 0, items: '> .o_kanban_record:not(.o_updating)', 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 495f98b28ee..361573fd3a1 100644 --- a/addons/web/static/src/js/views/kanban/kanban_record.js +++ b/addons/web/static/src/js/views/kanban/kanban_record.js @@ -36,7 +36,6 @@ var KanbanRecord = Widget.extend({ this.options = options; this.editable = options.editable; this.deletable = options.deletable; - this.draggable = options.draggable; this.read_only_mode = options.read_only_mode; this.qweb = options.qweb; this.subWidgets = {}; diff --git a/addons/web/static/src/js/views/kanban/kanban_renderer.js b/addons/web/static/src/js/views/kanban/kanban_renderer.js index c9239d97d03..029cef7cf0b 100644 --- a/addons/web/static/src/js/views/kanban/kanban_renderer.js +++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js @@ -323,7 +323,7 @@ var KanbanRenderer = BasicRenderer.extend({ var groupByFieldInfo = state.fieldsInfo.kanban[state.groupedBy[0]]; // Deactivate the drag'n'drop if the groupedBy field: // - is a date or datetime since we group by month or - // - is readonly + // - is readonly (on the field attrs or in the view) var draggable = true; if (groupByFieldAttrs) { if (groupByFieldAttrs.type === "date" || groupByFieldAttrs.type === "datetime") { @@ -332,6 +332,11 @@ var KanbanRenderer = BasicRenderer.extend({ draggable = !(groupByFieldAttrs.readonly); } } + if (groupByFieldInfo) { + if (draggable && groupByFieldInfo.readonly !== undefined) { + draggable = !(groupByFieldInfo.readonly); + } + } this.groupedByM2O = groupByFieldAttrs && (groupByFieldAttrs.type === 'many2one'); var grouped_by_field = this.groupedByM2O && groupByFieldAttrs.relation; var groupByTooltip = groupByFieldInfo && groupByFieldInfo.options.group_by_tooltip; diff --git a/addons/web/static/src/less/layout_boxed.less b/addons/web/static/src/less/layout_boxed.less index a81e09f347b..21fcf66efc5 100644 --- a/addons/web/static/src/less/layout_boxed.less +++ b/addons/web/static/src/less/layout_boxed.less @@ -15,6 +15,7 @@ } } .o_boxed_footer { + white-space: nowrap; border-top: 3px solid @gray; ul { margin: 4px 0; |
