diff options
Diffstat (limited to 'addons/web/static/src')
19 files changed, 126 insertions, 43 deletions
diff --git a/addons/web/static/src/js/chrome/pager.js b/addons/web/static/src/js/chrome/pager.js index bbe69c6d86a..c7f22a6f2c9 100644 --- a/addons/web/static/src/js/chrome/pager.js +++ b/addons/web/static/src/js/chrome/pager.js @@ -97,10 +97,16 @@ var Pager = Widget.extend({ /** * Sets the state of the pager and renders it * @param {Object} [state] the values to update (size, current_min and limit) + * @param {Object} [options] + * @param {boolean} [options.notifyChange] set to true to make the pager + * notify the environment that its state changed */ - updateState: function (state) { + updateState: function (state, options) { _.extend(this.state, state); this._render(); + if (options && options.notifyChange) { + this.trigger('pager_changed', _.clone(this.state)); + } }, //-------------------------------------------------------------------------- diff --git a/addons/web/static/src/js/chrome/view_manager.js b/addons/web/static/src/js/chrome/view_manager.js index 2dae906c6db..d89f035d34d 100644 --- a/addons/web/static/src/js/chrome/view_manager.js +++ b/addons/web/static/src/js/chrome/view_manager.js @@ -363,7 +363,7 @@ var ViewManager = Widget.extend(ControlPanelMixin, { var View = this.registry.get(arch.attrs.js_class || view_descr.type); var params = _.extend({}, view_options, {userContext: this.getSession().user_context}); if (view_descr.type === "form" && ((this.action.target === 'new' || this.action.target === 'inline') || - (view_options && view_options.mode === 'edit'))) { + (view_options && (view_options.mode === 'edit' || view_options.context.form_view_initial_mode)))) { params.mode = params.initial_mode || 'edit'; } view_descr.searchview_hidden = View.prototype.searchview_hidden; diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index a1f87a38fd2..4c4671275f2 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -846,6 +846,13 @@ var HandleWidget = AbstractField.extend({ tagName: 'span', description: "", supportedFieldTypes: ['integer'], + + /* + * @override + */ + isSet: function () { + return true; + }, }); var FieldEmail = InputField.extend({ @@ -1787,7 +1794,7 @@ var FieldProgressBar = AbstractField.extend({ } else { this.$el.on('click', function () { if (!self.write_mode) { - var $input = $('<input>', {type: 'text', class: 'o_progressbar_value'}); + var $input = $('<input>', {type: 'text', class: 'o_progressbar_value o_input'}); $input.on('blur', _.bind(self.on_change_input, self)); self.$('.o_progressbar_value').replaceWith($input); self.write_mode = true; diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index ba9b947d6a3..f396699bc3d 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -1087,7 +1087,11 @@ var FieldOne2Many = FieldX2Many.extend({ ev.stopPropagation(); if (this.editable) { - if (!this.creatingRecord) { + if (!this.activeActions.create) { + if (ev.data.onFail) { + ev.data.onFail(); + } + } else if (!this.creatingRecord) { this.creatingRecord = true; this._setValue({ operation: 'CREATE', diff --git a/addons/web/static/src/js/services/data_manager.js b/addons/web/static/src/js/services/data_manager.js index 999a9d8df01..77857ef2d31 100644 --- a/addons/web/static/src/js/services/data_manager.js +++ b/addons/web/static/src/js/services/data_manager.js @@ -398,11 +398,6 @@ return core.Class.extend({ */ _processFieldsView: function (viewInfo) { var viewFields = this._processFields(viewInfo.type, viewInfo.arch, viewInfo.fields); - // by default fetch display_name and id - if (!viewInfo.fields.display_name) { - viewInfo.fields.display_name = {type: 'char'}; - viewFields.display_name = {}; - } viewInfo.fieldsInfo = {}; viewInfo.fieldsInfo[viewInfo.type] = viewFields; utils.deepFreeze(viewInfo.fields); 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 cfdee6793dd..67de3ec8ad9 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -539,6 +539,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { * reload */ _onReload: function (event) { + event.stopPropagation(); // prevent other controllers from handling this request var data = event && event.data || {}; var handle = data.db_id; if (handle) { @@ -546,7 +547,10 @@ var BasicController = AbstractController.extend(FieldManagerMixin, { this.model.reload(handle).then(this._confirmSave.bind(this, handle)); } else { // no db_id given, so reload the main record - this.reload({fieldNames: data.fieldNames}); + this.reload({ + fieldNames: data.fieldNames, + keepChanges: data.keepChanges || false, + }); } }, /** 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 537fa11fdb9..5eca6c5374f 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1631,8 +1631,8 @@ var BasicModel = AbstractModel.extend({ */ _fetchRecord: function (record, options) { var self = this; - var fieldNames = options && options.fieldNames || - _.uniq(record.getFieldNames().concat(['display_name'])); + var fieldNames = options && options.fieldNames || record.getFieldNames(); + fieldNames = _.uniq(fieldNames.concat(['display_name'])); return this._rpc({ model: record.model, method: 'read', @@ -2045,7 +2045,7 @@ var BasicModel = AbstractModel.extend({ if (record.data.hasOwnProperty(domainModel)) { domainModel = record._changes && record._changes[domainModel] || record.data[domainModel]; } - var domainValue = record._changes && record._changes[fieldName] || record.data[fieldName]; + var domainValue = record._changes && record._changes[fieldName] || record.data[fieldName] || []; // avoid rpc if not necessary var hasChanged = this._saveSpecialDataCache(record, fieldName, { @@ -2339,6 +2339,16 @@ var BasicModel = AbstractModel.extend({ _generateOnChangeData: function (record) { var commands = this._generateX2ManyCommands(record, {withReadonly: true}); var data = _.extend(this.get(record.id, {raw: true}).data, commands); + // 'display_name' is automatically added to the list of fields to fetch, + // when fetching a record, even if it doesn't appear in the view. However, + // only the fields in the view must be passed to the onchange RPC, so we + // remove it from the data sent by RPC if it isn't in the view. + var hasDisplayName = _.some(record.fieldsInfo, function (fieldsInfo) { + return 'display_name' in fieldsInfo; + }); + if (!hasDisplayName) { + delete data.display_name; + } // one2many records have a parentID if (record.parentID) { @@ -2399,7 +2409,10 @@ var BasicModel = AbstractModel.extend({ _.each(list._changes, function (change) { if (change.operation === 'ADD') { relRecordAdded.push(self.localData[change.id]); - } else if (change.operation === 'UPDATE') { + } else if (change.operation === 'UPDATE' && !self.isNew(change.id)) { + // ignore new records that would have been updated + // afterwards, as all their changes would already + // be aggregated in the CREATE command relRecordUpdated.push(self.localData[change.id]); } }); @@ -2740,8 +2753,7 @@ var BasicModel = AbstractModel.extend({ var fieldInfo = element.fieldsInfo[element.viewType][fieldName]; var rawModifiers = JSON.parse(fieldInfo.modifiers || "{}"); var modifiers = self._evalModifiers(record, rawModifiers); - var required = 'required' in modifiers ? modifiers.required : field.required; - if (required && !self._isFieldSet(recordData[fieldName], field.type)) { + if (modifiers.required && !self._isFieldSet(recordData[fieldName], field.type)) { isValid = false; } }); 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 1ee7bf4a501..aaf7e4a5859 100644 --- a/addons/web/static/src/js/views/field_manager_mixin.js +++ b/addons/web/static/src/js/views/field_manager_mixin.js @@ -120,6 +120,7 @@ var FieldManagerMixin = { */ _onLoad: function (event) { var self = this; + event.stopPropagation(); // prevent other field managers from handling this request var data = event.data; if (!data.on_success) { return; } var params = {}; 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 0718b4e202e..0bd3c263666 100644 --- a/addons/web/static/src/js/views/form/form_controller.js +++ b/addons/web/static/src/js/views/form/form_controller.js @@ -28,6 +28,7 @@ var FormController = BasicController.extend({ this._super.apply(this, arguments); this.actionButtons = params.actionButtons; + this.disableAutofocus = params.disableAutofocus; this.footerToButtons = params.footerToButtons; this.defaultButtons = params.defaultButtons; this.hasSidebar = params.hasSidebar; @@ -42,7 +43,9 @@ var FormController = BasicController.extend({ * Calls autofocus on the renderer */ autofocus: function () { - this.renderer.autofocus(); + if (!this.disableAutofocus) { + this.renderer.autofocus(); + } }, /** * This method switches the form view in edit mode, with a new record. @@ -305,7 +308,7 @@ var FormController = BasicController.extend({ this.set('title', title); this._updateButtons(); this._updateSidebar(); - return this._super.apply(this, arguments); + return this._super.apply(this, arguments).then(this.autofocus.bind(this)); }, /** * @private 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 1d788ac2c05..63d7fd44917 100644 --- a/addons/web/static/src/js/views/form/form_renderer.js +++ b/addons/web/static/src/js/views/form/form_renderer.js @@ -246,10 +246,6 @@ var FormRenderer = BasicRenderer.extend({ _renderButtonBox: function (node) { var self = this; var $result = $('<' + node.tag + '>', { 'class': 'o_not_full' }); - // Avoid to show buttons if we are in create mode (edit mode without res_id) - if (this.mode === 'edit' && !this.state.res_id) { - return $result; - } var buttons = _.map(node.children, function (child) { if (child.tag === 'button') { return self._renderStatButton(child); @@ -816,9 +812,6 @@ var FormRenderer = BasicRenderer.extend({ self._addFieldTooltip(widget, $label); } }); - - // Focus the default field (in edit mode) - self.autofocus(); }, /** * Sets id attribute of given widget to idForLabel 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 f0264b67307..b48a5488848 100644 --- a/addons/web/static/src/js/views/form/form_view.js +++ b/addons/web/static/src/js/views/form/form_view.js @@ -29,6 +29,7 @@ var FormView = BasicView.extend({ this.loadParams.type = 'record'; this.loadParams.parentID = params.parentID; + this.controllerParams.disableAutofocus = params.disable_autofocus; this.controllerParams.hasSidebar = params.sidebar; this.controllerParams.toolbarActions = viewInfo.toolbar; this.controllerParams.footerToButtons = params.footer_to_buttons; diff --git a/addons/web/static/src/js/views/graph/graph_controller.js b/addons/web/static/src/js/views/graph/graph_controller.js index d68808bac1d..77e3f1e7a40 100644 --- a/addons/web/static/src/js/views/graph/graph_controller.js +++ b/addons/web/static/src/js/views/graph/graph_controller.js @@ -102,10 +102,20 @@ var GraphController = AbstractController.extend({ }); }, /** + * @private + */ + _update: function () { + this._updateButtons(); + return this._super.apply(this, arguments); + }, + /** * makes sure that the buttons in the control panel matches the current * state (so, correct active buttons and stuff like that) */ _updateButtons: function () { + if (!this.$buttons) { + return; + } var state = this.model.get(); this.$buttons.find('.o_graph_button').removeClass('active'); this.$buttons diff --git a/addons/web/static/src/js/views/graph/graph_model.js b/addons/web/static/src/js/views/graph/graph_model.js index 50e9f224697..a6d2b057d0e 100644 --- a/addons/web/static/src/js/views/graph/graph_model.js +++ b/addons/web/static/src/js/views/graph/graph_model.js @@ -55,14 +55,15 @@ return AbstractModel.extend({ * to keep track of various entities. */ load: function (params) { - this.initialGroupBys = params.groupBys; + var groupBys = params.context.graph_groupbys || params.groupBys; + this.initialGroupBys = groupBys; this.fields = params.fields; this.modelName = params.modelName; this.chart = { data: [], - groupedBy: params.groupedBy.length ? params.groupedBy : params.groupBys, - measure: params.measure, - mode: params.mode, + groupedBy: params.groupedBy.length ? params.groupedBy : groupBys, + measure: params.context.graph_measure || params.measure, + mode: params.context.graph_mode || params.mode, domain: params.domain, context: params.context, }; @@ -85,6 +86,12 @@ return AbstractModel.extend({ * @returns {Deferred} */ reload: function (handle, params) { + if ('context' in params) { + this.chart.context = params.context; + this.chart.groupedBy = params.context.graph_groupbys || this.chart.groupedBy; + this.chart.measure = params.context.graph_measure || this.chart.measure; + this.chart.mode = params.context.graph_mode || this.chart.mode; + } if ('domain' in params) { this.chart.domain = params.domain; } diff --git a/addons/web/static/src/js/views/graph/graph_view.js b/addons/web/static/src/js/views/graph/graph_view.js index 08b5ce1968f..423d52ca64c 100644 --- a/addons/web/static/src/js/views/graph/graph_view.js +++ b/addons/web/static/src/js/views/graph/graph_view.js @@ -27,7 +27,7 @@ var GraphView = AbstractView.extend({ /** * @override */ - init: function (viewInfo, params) { + init: function (viewInfo) { this._super.apply(this, arguments); var measure; @@ -57,9 +57,9 @@ var GraphView = AbstractView.extend({ this.controllerParams.measures = measures; this.rendererParams.stacked = viewInfo.arch.attrs.stacked !== "False"; - this.loadParams.mode = params.context.graph_mode || viewInfo.arch.attrs.type || 'bar'; - this.loadParams.measure = params.context.graph_measure || measure || '__count__'; - this.loadParams.groupBys = params.context.graph_groupbys || groupBys || []; + this.loadParams.mode = viewInfo.arch.attrs.type || 'bar'; + this.loadParams.measure = measure || '__count__'; + this.loadParams.groupBys = groupBys || []; this.loadParams.fields = viewInfo.fields; }, }); diff --git a/addons/web/static/src/js/views/list/list_controller.js b/addons/web/static/src/js/views/list/list_controller.js index 3b74f140e4d..33637e53f52 100644 --- a/addons/web/static/src/js/views/list/list_controller.js +++ b/addons/web/static/src/js/views/list/list_controller.js @@ -313,7 +313,11 @@ var ListController = BasicController.extend({ */ _onAddRecord: function (event) { event.stopPropagation(); - this._addRecord(); + if (this.activeActions.create) { + this._addRecord(); + } else if (event.data.onFail) { + event.data.onFail(); + } }, /** * Handles a click on a button by performing its action. 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 3cd93bb6e8b..c5f65ecc6e2 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 @@ -341,7 +341,12 @@ ListRenderer.include({ if (this.currentRow < this.state.data.length - 1) { this._selectCell(this.currentRow + 1, 0); } else { - this.unselectRow().then(this.trigger_up.bind(this, 'add_record')); + var self = this; + this.unselectRow().then(function () { + self.trigger_up('add_record', { + onFail: self._selectCell.bind(self, 0, 0, {}), + }); + }); } }, /** 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 d74af7fee22..7eb2ba4bc6b 100644 --- a/addons/web/static/src/js/views/pivot/pivot_model.js +++ b/addons/web/static/src/js/views/pivot/pivot_model.js @@ -223,15 +223,15 @@ var PivotModel = AbstractModel.extend({ */ load: function (params) { this.initialDomain = params.domain; - this.initialRowGroupBys = params.rowGroupBys; + this.initialRowGroupBys = params.context.pivot_row_groupby || params.rowGroupBys; this.fields = params.fields; this.modelName = params.modelName; this.data = { domain: params.domain, context: _.extend({}, session.user_context, params.context), groupedBy: params.groupedBy, - colGroupBys: params.colGroupBys, - measures: params.measures, + colGroupBys: params.context.pivot_column_groupby || params.colGroupBys, + measures: this._processMeasures(params.context.pivot_measures) || params.measures, sorted_column: {}, }; this.defaultGroupedBy = params.groupedBy; @@ -245,6 +245,12 @@ var PivotModel = AbstractModel.extend({ */ reload: function (handle, params) { var self = this; + if ('context' in params) { + this.data.context = params.context; + this.data.colGroupBys = params.context.pivot_column_groupby || this.data.colGroupBys; + this.data.groupedBy = params.context.pivot_row_groupby || this.data.groupedBy; + this.data.measures = this._processMeasures(params.context.pivot_measures) || this.data.measures; + } if ('domain' in params) { this.data.domain = params.domain; } else { @@ -261,7 +267,7 @@ var PivotModel = AbstractModel.extend({ var old_col_root = this.data.main_col.root; return this._loadData().then(function () { var new_groupby_length; - if (!('groupBy' in params)) { + if (!('groupBy' in params) && !('pivot_row_groupby' in (params.context || {}))) { // we only update the row groupbys according to the old groupbys // if we don't have the key 'groupBy' in params. In that case, // we want to have the full open state for the groupbys. @@ -649,6 +655,29 @@ var PivotModel = AbstractModel.extend({ this.data.main_col.root = main_col_header; }, /** + * In the preview implementation of the pivot view (a.k.a. version 2), + * the virtual field used to display the number of records was named + * __count__, whereas __count is actually the one used in xml. So + * basically, activating a filter specifying __count as measures crashed. + * Unfortunately, as __count__ was used in the JS, all filters saved as + * favorite at that time were saved with __count__, and not __count. + * So in order the make them still work with the new implementation, we + * handle both __count__ and __count. + * + * This function replaces in the given array of measures occurences of + * '__count__' by '__count'. + * + * @param {Array[string] || undefined} measures + * @return {Array[string] || undefined} + */ + _processMeasures: function (measures) { + if (measures) { + return _.map(measures, function (measure) { + return measure === '__count__' ? '__count' : measure; + }); + } + }, + /** * Format a value to a usable string, for the renderer to display. * * @param {any} value 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 356672081d9..7e4dddc4a52 100644 --- a/addons/web/static/src/js/views/pivot/pivot_view.js +++ b/addons/web/static/src/js/views/pivot/pivot_view.js @@ -87,9 +87,9 @@ var PivotView = AbstractView.extend({ activeMeasures.push('__count'); } - this.loadParams.measures = params.context.pivot_measures || activeMeasures; - this.loadParams.colGroupBys = params.context.pivot_column_groupby || colGroupBys; - this.loadParams.rowGroupBys = params.context.pivot_row_groupby || rowGroupBys; + this.loadParams.measures = activeMeasures; + this.loadParams.colGroupBys = colGroupBys; + this.loadParams.rowGroupBys = rowGroupBys; this.loadParams.fields = fields; this.controllerParams.title = params.title || arch.attrs.string || _t("Untitled"); diff --git a/addons/web/static/src/less/list_view.less b/addons/web/static/src/less/list_view.less index b7e362cc57f..f509e82345c 100644 --- a/addons/web/static/src/less/list_view.less +++ b/addons/web/static/src/less/list_view.less @@ -118,7 +118,9 @@ } .o_data_cell.o_invisible_modifier { - display: table-cell!important; // Override invisible to keep the cells aligned + // Override display: none to keep table cells aligned. Note: cannot use + // 'initial' as it will force them to 'inline', not 'table-cell'. + display: table-cell!important; } //-------------------------------------------------------------------------- |
