diff options
Diffstat (limited to 'addons/web/static/src/js/views')
10 files changed, 107 insertions, 73 deletions
diff --git a/addons/web/static/src/js/views/abstract_model.js b/addons/web/static/src/js/views/abstract_model.js index 27d13a12b06..4ea6b217e65 100644 --- a/addons/web/static/src/js/views/abstract_model.js +++ b/addons/web/static/src/js/views/abstract_model.js @@ -15,6 +15,7 @@ odoo.define('web.AbstractModel', function (require) { */ var Class = require('web.Class'); +var fieldUtils = require('web.field_utils'); var mixins = require('web.mixins'); var ServicesMixin = require('web.ServicesMixin'); @@ -63,6 +64,30 @@ var AbstractModel = Class.extend(mixins.EventDispatcherMixin, ServicesMixin, { reload: function (params) { return $.when(); }, + /** + * Processes date(time) and selection field values sent by the server. + * Converts data(time) values to moment instances. + * Converts false values of selection fields to 0 if 0 is a valid key, + * because the server doesn't make a distinction between false and 0, and + * always sends false when value is 0. + * + * @param {Object} field the field description + * @param {*} value + * @returns {*} the processed value + */ + _parseServerValue: function (field, value) { + if (field.type === 'date' || field.type === 'datetime') { + // process date(time): convert into a moment instance + value = fieldUtils.parse[field.type](value, field, {isUTC: true}); + } else if (field.type === 'selection' && value === false) { + // process selection: convert false to 0, if 0 is a valid key + var hasKey0 = _.find(field.selection, function (option) { + return option[0] === 0; + }); + value = hasKey0 ? 0 : value; + } + return value; + }, }); return AbstractModel; 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 5fb77204ec7..75a0ad02971 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -84,10 +84,9 @@ odoo.define('web.BasicModel', function (require) { var AbstractModel = require('web.AbstractModel'); var concurrency = require('web.concurrency'); -var core = require('web.core'); var Context = require('web.Context'); +var core = require('web.core'); var Domain = require('web.Domain'); -var fieldUtils = require('web.field_utils'); var session = require('web.session'); var _t = core._t; @@ -2370,8 +2369,8 @@ var BasicModel = AbstractModel.extend({ * if given, this field's context is added to the context, instead of * the element's context (except if options.full is true) * @param {boolean} [options.full=false] - * if true and fieldName given in options, the element's context - * is added to the context + * if true or nor fieldName or additionalContext given in options, + * the element's context is added to the context * @returns {Object} the evaluated context */ _getContext: function (element, options) { @@ -2379,7 +2378,7 @@ var BasicModel = AbstractModel.extend({ var context = new Context(session.user_context); context.set_eval_context(this._getEvalContext(element)); - if (options.full || !options.fieldName) { + if (options.full || !(options.fieldName || options.additionalContext)) { context.add(element.context); } if (options.fieldName) { @@ -2656,8 +2655,14 @@ var BasicModel = AbstractModel.extend({ var type = params.type || ('domain' in params && 'list') || 'record'; var res_id, value; var res_ids = params.res_ids || []; + var data = params.data || (type === 'record' ? {} : []); if (type === 'record') { - res_id = params.res_id || (params.data && params.data.id) || _.uniqueId('virtual_'); + res_id = params.res_id || (params.data && params.data.id); + if (res_id) { + data.id = res_id; + } else { + res_id = _.uniqueId('virtual_'); + } } else { var isValueArray = params.value instanceof Array; res_id = isValueArray ? params.value[0] : undefined; @@ -2675,7 +2680,7 @@ var BasicModel = AbstractModel.extend({ aggregateValues: params.aggregateValues || {}, context: params.context || {}, count: params.count || res_ids.length, - data: params.data || (type === 'record' ? {} : []), + data: data, domain: params.domain || [], fields: fields, fieldsInfo: params.fieldsInfo, @@ -2941,30 +2946,6 @@ var BasicModel = AbstractModel.extend({ }); }, /** - * Processes date(time) and selection field values sent by the server. - * Converts data(time) values to moment instances. - * Converts false values of selection fields to 0 if 0 is a valid key, - * because the server doesn't make a distinction between false and 0, and - * always sends false when value is 0. - * - * @param {Object} field the field description - * @param {*} value - * @returns {*} the processed value - */ - _parseServerValue: function (field, value) { - if (field.type === 'date' || field.type === 'datetime') { - // process date(time): convert into a moment instance - value = fieldUtils.parse[field.type](value, field, {isUTC: true}); - } else if (field.type === 'selection' && value === false) { - // process selection: convert false to 0, if 0 is a valid key - var hasKey0 = _.find(field.selection, function (option) { - return option[0] === 0; - }); - value = hasKey0 ? 0 : value; - } - return value; - }, - /** * This method is quite important: it is supposed to perform the /onchange * rpc and apply the result. * @@ -3087,7 +3068,8 @@ var BasicModel = AbstractModel.extend({ lazy: true, }) .then(function (groups) { - var rawGroupBy = list.groupedBy[0].split(':')[0]; + var groupByField = list.groupedBy[0]; + var rawGroupBy = groupByField.split(':')[0]; var previousGroups = _.map(list.data, function (groupID) { return self.localData[groupID]; }); @@ -3098,13 +3080,13 @@ var BasicModel = AbstractModel.extend({ _.each(groups, function (group) { var aggregateValues = {}; _.each(group, function (value, key) { - if (_.contains(fields, key) && key !== list.groupedBy[0]) { + if (_.contains(fields, key) && key !== groupByField) { aggregateValues[key] = value; } }); // When a view is grouped, we need to display the name of each group in // the 'title'. - var value = group[rawGroupBy]; + var value = group[groupByField]; if (list.fields[rawGroupBy].type === "selection") { var choice = _.find(list.fields[rawGroupBy].selection, function (c) { return c[0] === value; 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 ded7938605f..73868a93fdb 100644 --- a/addons/web/static/src/js/views/calendar/calendar_model.js +++ b/addons/web/static/src/js/views/calendar/calendar_model.js @@ -406,12 +406,13 @@ return AbstractModel.extend({ }); } return eventsDef.then(function (events) { - self.data.data = _.map(events, self._recordToCalendarEvent.bind(self)); - return $.when( - self._loadColors(self.data, self.data.data), - self._loadRecordsToFilters(self.data, self.data.data) - ); - }); + self._parseServerData(events); + self.data.data = _.map(events, self._recordToCalendarEvent.bind(self)); + return $.when( + self._loadColors(self.data, self.data.data), + self._loadRecordsToFilters(self.data, self.data.data) + ); + }); }); }, /** @@ -566,12 +567,25 @@ return AbstractModel.extend({ if (filter.filters.length && (filter.filters[0].avatar_model in to_read)) { _.each(filter.filters, function (f) { f.label = to_read[f.avatar_model][f.value]; - }); + }); } }); }); }, /** + * parse the server values to javascript framwork + * + * @param {Object} data the server data to parse + */ + _parseServerData: function (data) { + var self = this; + _.each(data, function(event) { + _.each(self.fieldNames, function (fieldName) { + event[fieldName] = self._parseServerValue(self.fields[fieldName], event[fieldName]); + }); + }); + }, + /** * Transform OpenERP event object to fullcalendar event object */ _recordToCalendarEvent: function (evt) { @@ -583,11 +597,11 @@ return AbstractModel.extend({ attendees = []; if (!all_day) { - date_start = fieldUtils.parse.datetime(evt[this.mapping.date_start]); - date_stop = this.mapping.date_stop ? fieldUtils.parse.datetime(evt[this.mapping.date_stop]) : null; + date_start = evt[this.mapping.date_start].clone(); + date_stop = this.mapping.date_stop ? evt[this.mapping.date_stop].clone() : null; } else { - date_start = fieldUtils.parse.datetime(evt[this.mapping.date_start].split(' ')[0]); - date_stop = this.mapping.date_stop ? fieldUtils.parse.datetime(evt[this.mapping.date_stop].split(' ')[0]) : null; + date_start = evt[this.mapping.date_start].clone().startOf('day'); + date_stop = this.mapping.date_stop ? evt[this.mapping.date_stop].clone().startOf('day') : null; } if (!date_stop && date_delay) { @@ -605,8 +619,8 @@ return AbstractModel.extend({ 'record': evt, 'start': date_start, 'end': date_stop, - 'r_start':date_start.clone(), - 'r_end':date_stop.clone(), + 'r_start': date_start, + 'r_end': date_stop, 'title': the_title, 'allDay': this.mapping.all_day && evt[this.mapping.all_day] || false, 'id': evt.id, diff --git a/addons/web/static/src/js/views/calendar/calendar_renderer.js b/addons/web/static/src/js/views/calendar/calendar_renderer.js index a4930c87d37..b61236131c6 100644 --- a/addons/web/static/src/js/views/calendar/calendar_renderer.js +++ b/addons/web/static/src/js/views/calendar/calendar_renderer.js @@ -288,7 +288,7 @@ return AbstractRenderer.extend({ if (field.type === "one2many" || field.type === "many2many") { return field_utils.format[field.type]({data: record[fieldName]}, field); } else { - return field_utils.format[field.type](record[fieldName], field); + return field_utils.format[field.type](record[fieldName], field, {forceString: true}); } }, /** 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 5948e07a54f..8a7f5da6d5d 100644 --- a/addons/web/static/src/js/views/graph/graph_model.js +++ b/addons/web/static/src/js/views/graph/graph_model.js @@ -60,12 +60,13 @@ return AbstractModel.extend({ this.modelName = params.modelName; this.chart = { data: [], - groupedBy: params.groupBys, + groupedBy: params.groupedBy.length ? params.groupedBy : params.groupBys, measure: params.measure, mode: params.mode, domain: params.domain, context: params.context, }; + this.defaultGroupedBy = params.groupedBy; return this._loadGraph(); }, /** @@ -88,11 +89,7 @@ return AbstractModel.extend({ this.chart.domain = params.domain; } if ('groupBy' in params) { - if (!params.groupBy.length) { - this.chart.groupedBy = this.initialGroupBys; - } else { - this.chart.groupedBy = params.groupBy; - } + this.chart.groupedBy = params.groupBy.length ? params.groupBy : this.defaultGroupedBy; } if ('measure' in params) { this.chart.measure = params.measure; diff --git a/addons/web/static/src/js/views/kanban/kanban_controller.js b/addons/web/static/src/js/views/kanban/kanban_controller.js index b5c60fe9ab3..2592e3d96ec 100644 --- a/addons/web/static/src/js/views/kanban/kanban_controller.js +++ b/addons/web/static/src/js/views/kanban/kanban_controller.js @@ -164,9 +164,10 @@ var KanbanController = BasicController.extend({ _onAddColumn: function (event) { var self = this; this.model.createGroup(event.data.value, this.handle).then(function () { - self.update({}, {reload: false}); + return self.update({}, {reload: false}); + }).then(function () { self._updateButtons(); - self.trigger_up('scrollTo', {selector: '.o_column_quick_create'}); + self.renderer.quickCreateToggleFold(); }); }, /** diff --git a/addons/web/static/src/js/views/kanban/kanban_quick_create.js b/addons/web/static/src/js/views/kanban/kanban_quick_create.js index 5e40352b26d..e81a290bf2d 100644 --- a/addons/web/static/src/js/views/kanban/kanban_quick_create.js +++ b/addons/web/static/src/js/views/kanban/kanban_quick_create.js @@ -192,7 +192,7 @@ var RecordQuickCreate = AbstractQuickCreate.extend({ var ColumnQuickCreate = AbstractQuickCreate.extend({ template: 'KanbanView.ColumnQuickCreate', events: _.extend({}, AbstractQuickCreate.prototype.events, { - 'click': '_onClick', + 'click': 'toggleFold', 'click input': '_onInputClicked', 'focusout': '_onFocusout', }), @@ -214,6 +214,22 @@ var ColumnQuickCreate = AbstractQuickCreate.extend({ }, //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Toggle fold/unfold the Column quick create widget + */ + toggleFold: function () { + this.folded = !this.folded; + this._update(); + if (!this.folded) { + this.$input.focus(); + this.trigger_up('scrollTo', {selector: '.o_column_quick_create'}); + } + }, + + //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- @@ -243,18 +259,6 @@ var ColumnQuickCreate = AbstractQuickCreate.extend({ /** * @private - * @param {MouseEvent} event - */ - _onClick: function () { - this.folded = !this.folded; - this._update(); - if (!this.folded) { - this.$input.focus(); - this.trigger_up('scrollTo', {selector: '.o_column_quick_create'}); - } - }, - /** - * @private */ _onFocusout: function () { var hasFocus = this.$(':focus').length > 0; 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 87275260b01..ea2f0270017 100644 --- a/addons/web/static/src/js/views/kanban/kanban_renderer.js +++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js @@ -113,6 +113,12 @@ var KanbanRenderer = BasicRenderer.extend({ this.widgets[0].addQuickCreate(); }, /** + * Toggle fold/unfold the Column quick create widget + */ + quickCreateToggleFold: function () { + this.quickCreate.toggleFold(); + }, + /** * Removes a widget (record if ungrouped, column if grouped) from the view. * * @param {Widget} widget the instance of the widget to remove @@ -244,8 +250,8 @@ var KanbanRenderer = BasicRenderer.extend({ // Enable column quickcreate if (this.columnOptions.group_creatable) { - var quickCreate = new ColumnQuickCreate(this); - quickCreate.appendTo(fragment); + this.quickCreate = new ColumnQuickCreate(this); + this.quickCreate.appendTo(fragment); } } 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 a917781b580..802f2f03a09 100644 --- a/addons/web/static/src/js/views/list/list_renderer.js +++ b/addons/web/static/src/js/views/list/list_renderer.js @@ -377,6 +377,10 @@ var ListRenderer = BasicRenderer.extend({ $cells.unshift($('<td>')); } var name = group.value === undefined ? _t('Undefined') : group.value; + var groupBy = this.state.groupedBy[groupLevel]; + if (group.fields[groupBy.split(':')[0]].type !== 'boolean') { + name = name || _t('Undefined'); + } var $th = $('<th>') .addClass('o_group_name') .text(name + ' (' + group.count + ')'); 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 49c00663d47..d74af7fee22 100644 --- a/addons/web/static/src/js/views/pivot/pivot_model.js +++ b/addons/web/static/src/js/views/pivot/pivot_model.js @@ -229,11 +229,12 @@ var PivotModel = AbstractModel.extend({ this.data = { domain: params.domain, context: _.extend({}, session.user_context, params.context), - groupedBy: params.rowGroupBys, + groupedBy: params.groupedBy, colGroupBys: params.colGroupBys, measures: params.measures, sorted_column: {}, }; + this.defaultGroupedBy = params.groupedBy; return this._loadData(); }, /** @@ -250,7 +251,7 @@ var PivotModel = AbstractModel.extend({ this.data.domain = this.initialDomain; } if ('groupBy' in params) { - this.data.groupedBy = params.groupBy; + this.data.groupedBy = params.groupBy.length ? params.groupBy : this.defaultGroupedBy; } if (!this.data.has_data) { return this._loadData(); |
