From 3d6420d4b3f062f12d7c18d7d9a976e2299b3444 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Tue, 25 Jul 2017 13:27:07 +0200 Subject: [FIX] web,*: display dashboard panel if no content *board,crm Before this rev., the dashboard panel (e.g. of the sales team dashboard) wasn't displayed when there were no record to display, whereas it should. Only the nocontent helper was displayed. This was a bug introduced with the new view: the views' controller was in charge to display the renderer (if there were data to display) xor the nocontent helper. As the dashboard panel was rendered by the renderer, it couldn't be displayed alongside the nocontent helper. This rev. moves this logic to the renderer. So now, the controller always contains the renderer, which decides what to render (the data or the nocontent helper). This way, the dashboards can display their panel and the nocontent helper. --- .../static/src/js/views/basic/basic_controller.js | 11 ---------- .../static/src/js/views/basic/basic_renderer.js | 24 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 11 deletions(-) (limited to 'addons/web/static/src/js/views/basic') 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 cc72816a85d..54c8ccfbf51 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -361,17 +361,6 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { model: this.modelName, }; }, - /** - * Used by list and kanban views to determine whether or not to display - * the no content helper (if there is no data in the state to display) - * - * @private - * @param {Object} state - * @returns {boolean} - */ - _hasContent: function (state) { - return state.count !== 0; - }, /** * Helper function to display a warning that some fields have an invalid * value. This is used when a save operation cannot be completed. 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 8bbf9ae45a4..e040a5fa7f0 100644 --- a/addons/web/static/src/js/views/basic/basic_renderer.js +++ b/addons/web/static/src/js/views/basic/basic_renderer.js @@ -317,6 +317,16 @@ var BasicRenderer = AbstractRenderer.extend({ _getModifiersData: function (node) { return _.findWhere(this.allModifiersData, {node: node}); }, + /** + * Used by list and kanban renderers to determine whether or not to display + * the no content helper (if there is no data in the state to display) + * + * @private + * @returns {boolean} + */ + _hasContent: function () { + return this.state.count !== 0; + }, /** * 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 @@ -486,6 +496,20 @@ var BasicRenderer = AbstractRenderer.extend({ return widget; }, + /** + * Renders the nocontent helper. + * + * This method is a helper for renderers that want to display a help + * message when no content is available. + * + * @private + */ + _renderNoContentHelper: function () { + var $msg = $('
') + .addClass('oe_view_nocontent') + .html(this.noContentHelp); + this.$el.html($msg); + }, /** * Actual rendering. Supposed to be overridden by concrete renderers. * The basic responsabilities of _renderView are: -- cgit v1.2.3 From 72ed3a153a1f4c718fee33ac8550298e8a29f6cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Wed, 26 Jul 2017 11:27:11 +0200 Subject: [FIX] web,pad: record is not considered dirty when pad is loaded The pad widget does something unconventional: it creates the pad url only when rendering in edit mode. This was done to prevent creating pad by default for record in readonly mode. Because of that, if the user clicks on create, then discard, the record was considered dirty, so a confirmation modal popped up. In this commit, we just make sure that the initial setValue from the rendering does not 'dirty' the record. --- .../web/static/src/js/views/basic/basic_model.js | 25 ++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'addons/web/static/src/js/views/basic') 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 8f679207f00..73cd2863f21 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -628,12 +628,12 @@ var BasicModel = AbstractModel.extend({ * * @param {string} record_id * @param {Object} changes a map field => new value - * @param {string} [viewType] current viewType. If not set, we will assume - * main viewType from the record + * @param {Object} [options] will be transferred to the applyChange method + * @see _applyChange * @returns {string[]} list of changed fields */ - notifyChanges: function (record_id, changes, viewType) { - return this.mutex.exec(this._applyChange.bind(this, record_id, changes, viewType)); + notifyChanges: function (record_id, changes, options) { + return this.mutex.exec(this._applyChange.bind(this, record_id, changes, options)); }, /** * Reload all data for a given resource @@ -956,23 +956,30 @@ var BasicModel = AbstractModel.extend({ * * @param {string} recordID * @param {Object} changes - * @param {string} [viewType] current viewType. If not set, we will assume + * @param {Object} [options] + * @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 {string} [options.viewType] current viewType. If not set, we will assume * main viewType from the record * @returns {Deferred} */ - _applyChange: function (recordID, changes, viewType) { + _applyChange: function (recordID, changes, options) { var self = this; var record = this.localData[recordID]; var field; var defs = []; + options = options || {}; record._changes = record._changes || {}; - record._isDirty = true; + if (!options.doNotSetDirty) { + record._isDirty = true; + } // apply changes to local data for (var fieldName in changes) { field = record.fields[fieldName]; if (field.type === 'one2many' || field.type === 'many2many') { - defs.push(this._applyX2ManyChange(record, fieldName, changes[fieldName], viewType)); + defs.push(this._applyX2ManyChange(record, fieldName, changes[fieldName], options.viewType)); } else if (field.type === 'many2one' || field.type === 'reference') { defs.push(this._applyX2OneChange(record, fieldName, changes[fieldName])); } else { @@ -993,7 +1000,7 @@ var BasicModel = AbstractModel.extend({ } var onchangeDef; if (onChangeFields.length) { - onchangeDef = self._performOnChange(record, onChangeFields, viewType).then(function (result) { + onchangeDef = self._performOnChange(record, onChangeFields, options.viewType).then(function (result) { delete record._warning; return _.keys(changes).concat(Object.keys(result && result.value || {})); }); -- cgit v1.2.3 From 3b3f6f04af79d7dcc4461262e14e05096d76180b Mon Sep 17 00:00:00 2001 From: David Monjoie Date: Wed, 26 Jul 2017 12:00:42 +0200 Subject: [FIX] web: save changes when readonly if force_save is set In previous versions, readonly used to prevent sending the values of the fields to the server. However, it was not working properly for fields which have their own sub-arch in the view, as the value used to be sent regardless of the readonly value. In the new views, the readonly modifier is never overlooked, which created a bug in the stock_picking_return wizard which was not able to return products received from a po anymore. Basically the value of the product_id field was not sent so the create crashed. This commit introduces a new "force_save" modifier which is used to express that we want to save the value of the field even though it is readonly from a user interface point of view. --- addons/web/static/src/js/views/basic/basic_model.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'addons/web/static/src/js/views/basic') 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 73cd2863f21..04fe384afdc 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -2203,7 +2203,7 @@ var BasicModel = AbstractModel.extend({ // remove readonly fields from the list of changes if (!withReadonly && fieldName in changes || fieldName in commands) { var editionViewType = record._editionViewType[fieldName] || viewType; - if (this._isFieldReadonly(record, fieldName, editionViewType)) { + if (this._isFieldProtected(record, fieldName, editionViewType)) { delete changes[fieldName]; continue; } @@ -2562,9 +2562,10 @@ var BasicModel = AbstractModel.extend({ return context; }, /** - * Returns true if the field is readonly (checking first in the modifiers, - * and if there is no readonly modifier, checking the readonly attribute of - * the field). + * Returns true if the field is protected against changes, looking for a + * readonly modifier unless there is a force_save modifier (checking first + * in the modifiers, and if there is no readonly modifier, checking the + * readonly attribute of the field). * * @private * @param {Object} record an element from the localData @@ -2573,12 +2574,12 @@ var BasicModel = AbstractModel.extend({ * main viewType from the record * @returns {boolean} */ - _isFieldReadonly: function (record, fieldName, viewType) { + _isFieldProtected: function (record, fieldName, viewType) { var fieldInfo = record.fieldsInfo[viewType || record.viewType][fieldName]; if (fieldInfo) { var rawModifiers = JSON.parse(fieldInfo.modifiers || "{}"); var modifiers = this._evalModifiers(record, rawModifiers); - return modifiers.readonly; + return modifiers.readonly && !fieldInfo.force_save; } else { return false; } -- cgit v1.2.3 From 28bf5f007fd777f7cf2c8f85ea9938b288d391f0 Mon Sep 17 00:00:00 2001 From: David Monjoie Date: Mon, 31 Jul 2017 14:48:50 +0200 Subject: [FIX] web: fix action context with no explicit context When I did efd15852, I accidentally undid d20074c5. That commit wanted to filter out unwanted values from the action context, but it was too violent, as it was discarding the action context. (See bug described in efd15852) My original commit aimed at avoiding the filtering of the action context by having it devoid of unwanted values altogether. The idea was "if this is an action button, we don't want the element context". However, the default behavior of the _getContext function was to add the element context. There were options to force to add the element context despite being in a case where it should not be added, but we needed the opposite: do not add the element context. We used "additionalContext" in this fashion, the idea was: "if I give you specific context values, don't polute it with the element context". This was efd15852. However, not all actions have context defined explicitely in their definition. In this case, since additionalContext was undefined, the element context was added again, despite our will not to add it for actions. We solved this by simply always giving an additionalContext to getContext, providing an empty one if needed. To reproduce this bug (which is the same as efd15852): - Go to Manufacturing - Click on menu Master Data then Products - Open a product - Click on the "Bills of Materials" stat button - Click on create - The create crashes because of the "default_type" context key that is erroneously passed from the "Products" action to the "Bills of Materials" stat button action. --- addons/web/static/src/js/views/basic/basic_controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/web/static/src/js/views/basic') 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 54c8ccfbf51..39e596db5b8 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -238,7 +238,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { var recordID = record.data.id; this.trigger_up('execute_action', { action_data: _.extend({}, attrs, { - context: record.getContext({additionalContext: attrs.context}), + context: record.getContext({additionalContext: attrs.context || {}}), }), model: record.model, res_ids: [recordID], -- cgit v1.2.3 From 211961c3747b5948e80ad8eb6f097636bc61b46d Mon Sep 17 00:00:00 2001 From: Martin Geubelle Date: Tue, 1 Aug 2017 17:55:24 +0200 Subject: [FIX] web: handle `mutexify` in standalone widgets The rev. https://github.com/odoo/odoo/commit/99ae418bf24171fbc6bb27584059c27efb857e77 introduced a trigger_up `mutexify` when quick creating a record in a many2one ; this broke the behaviour when the many2one was standalone (because it has no BasicController and mutexify is handled in the latter). An attempt to fix this issue has been made in the rev. https://github.com/odoo/odoo/commit/e83c3e2678500c9bf2c17b4d23ae9a294ebafaa7 by adding an option `standalone` in the field widget options. In this case, the action was directly executed instead of the trigger_up. While this correctly works, this implies that the option needs to be added in every standalone many2one (and only many2one as the others won't use the option), which is not very convenient. An other attempt is made in this rev. by moving the mutexify handler from the BasicController to the FieldManagerMixin ; as a widget that instantiates a field widget needs to extend this mixin, both cases will work and we won't need to specify the option anymore. This commit thus partially reverts the rev. https://github.com/odoo/odoo/commit/e83c3e2678500c9bf2c17b4d23ae9a294ebafaa7 --- addons/web/static/src/js/views/basic/basic_controller.js | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'addons/web/static/src/js/views/basic') 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 39e596db5b8..3a47f65ab03 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -8,7 +8,6 @@ odoo.define('web.BasicController', function (require) { */ var AbstractController = require('web.AbstractController'); -var concurrency = require('web.concurrency'); var core = require('web.core'); var Dialog = require('web.Dialog'); var FieldManagerMixin = require('web.FieldManagerMixin'); @@ -19,7 +18,6 @@ var _t = core._t; var BasicController = AbstractController.extend(FieldManagerMixin, { custom_events: _.extend({}, AbstractController.prototype.custom_events, FieldManagerMixin.custom_events, { discard_changes: '_onDiscardChanges', - mutexify: '_onMutexify', reload: '_onReload', sidebar_data_asked: '_onSidebarDataAsked', translate: '_onTranslate', @@ -39,7 +37,6 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { FieldManagerMixin.init.call(this, this.model); this.handle = params.initialState.id; this.mode = params.mode || 'readonly'; - this.mutex = new concurrency.Mutex(); }, /** * @override @@ -526,15 +523,6 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { } FieldManagerMixin._onFieldChanged.apply(this, arguments); }, - /** - * @private - * @param {OdooEvent} ev - * @param {function} ev.data.action the function to execute in the mutex - */ - _onMutexify: function (ev) { - ev.stopPropagation(); // prevent other controllers from handling this request - this.mutex.exec(ev.data.action); - }, /** * When a reload event triggers up, we need to reload the full view. * For example, after a form view dialog saved some data. -- cgit v1.2.3