summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src/js/views')
-rw-r--r--addons/web/static/src/js/views/abstract_controller.js27
-rw-r--r--addons/web/static/src/js/views/abstract_renderer.js2
-rw-r--r--addons/web/static/src/js/views/abstract_view.js2
-rw-r--r--addons/web/static/src/js/views/basic/basic_controller.js11
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js24
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_controller.js24
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_renderer.js106
-rw-r--r--addons/web/static/src/js/views/list/list_controller.js5
-rw-r--r--addons/web/static/src/js/views/list/list_renderer.js15
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_controller.js15
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_renderer.js22
11 files changed, 137 insertions, 116 deletions
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js
index b84f6ec1951..3bdf8ab08ca 100644
--- a/addons/web/static/src/js/views/abstract_controller.js
+++ b/addons/web/static/src/js/views/abstract_controller.js
@@ -32,7 +32,6 @@ var AbstractController = Widget.extend({
* @param {string} params.modelName
* @param {any} [params.handle] a handle that will be given to the model (some id)
* @param {any} params.initialState the initialState
- * @param {string} [params.noContentHelp]
*/
init: function (parent, model, renderer, params) {
this._super.apply(this, arguments);
@@ -42,7 +41,6 @@ var AbstractController = Widget.extend({
this.handle = params.handle;
this.activeActions = params.activeActions;
this.initialState = params.initialState;
- this.noContentHelp = params.noContentHelp;
},
/**
* Simply renders and updates the url.
@@ -224,31 +222,6 @@ var AbstractController = Widget.extend({
this.trigger_up('push_state', state || {});
},
/**
- * Hide or show the nocontent helper. For this, it also remove the renderer
- * from the dom, and reattach it when necessary.
- *
- * This method is a helper for controllers that want to display a help
- * message when no content is available. It is suggested to override
- * _update to call this method.
- *
- * @private
- * @param {boolean} hasNoContent
- */
- _toggleNoContentHelper: function (hasNoContent) {
- if (hasNoContent && this.noContentHelp) {
- this.renderer.$el.detach();
- var $msg = $('<div>')
- .addClass('oe_view_nocontent')
- .html(this.noContentHelp);
- this.$el.html($msg);
- } else {
- if (!document.contains(this.renderer.el)) {
- this.$('div.oe_view_nocontent').remove();
- this.$el.append(this.renderer.$el);
- }
- }
- },
- /**
* This method is called after each update or when the start method is
* completed.
*
diff --git a/addons/web/static/src/js/views/abstract_renderer.js b/addons/web/static/src/js/views/abstract_renderer.js
index 7d10f05eab8..d7eb5002f2d 100644
--- a/addons/web/static/src/js/views/abstract_renderer.js
+++ b/addons/web/static/src/js/views/abstract_renderer.js
@@ -15,11 +15,13 @@ return Widget.extend({
* @param {Widget} parent
* @param {any} state
* @param {Object} params
+ * @param {string} [params.noContentHelp]
*/
init: function (parent, state, params) {
this._super(parent);
this.state = state;
this.arch = params.arch;
+ this.noContentHelp = params.noContentHelp;
},
/**
* The rendering can be asynchronous (but it is not encouraged). The start
diff --git a/addons/web/static/src/js/views/abstract_view.js b/addons/web/static/src/js/views/abstract_view.js
index e14e064ee33..74e1e1fce18 100644
--- a/addons/web/static/src/js/views/abstract_view.js
+++ b/addons/web/static/src/js/views/abstract_view.js
@@ -77,6 +77,7 @@ var AbstractView = Class.extend({
init: function (viewInfo, params) {
this.rendererParams = {
arch: viewInfo.arch,
+ noContentHelp: params.action && params.action.help,
};
this.controllerParams = {
@@ -87,7 +88,6 @@ var AbstractView = Class.extend({
delete: viewInfo.arch.attrs.delete ? JSON.parse(viewInfo.arch.attrs.delete) : true,
duplicate: viewInfo.arch.attrs.duplicate ? JSON.parse(viewInfo.arch.attrs.duplicate) : true,
},
- noContentHelp: params.action && params.action.help,
};
this.loadParams = {
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
@@ -362,17 +362,6 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
};
},
/**
- * 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
@@ -318,6 +318,16 @@ var BasicRenderer = AbstractRenderer.extend({
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
* renderers:
@@ -487,6 +497,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 = $('<div>')
+ .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:
* - use the xml arch of the view to render a jQuery representation
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 2592e3d96ec..2cf6a94285e 100644
--- a/addons/web/static/src/js/views/kanban/kanban_controller.js
+++ b/addons/web/static/src/js/views/kanban/kanban_controller.js
@@ -81,19 +81,6 @@ var KanbanController = BasicController.extend({
return this.renderer.updateRecord(this.model.get(id));
},
/**
- * The nocontent helper should be displayed in kanban:
- * - ungrouped: if there is no records
- * - grouped: if there is no groups and no column quick create
- *
- * @override
- * @private
- */
- _hasContent: function (state) {
- return this._super.apply(this, arguments) ||
- this.createColumnEnabled ||
- (state.groupedBy.length && state.data.length);
- },
- /**
* The column quick create should be displayed in kanban iff grouped by an
* m2o field and group_create action enabled.
*
@@ -138,17 +125,6 @@ var KanbanController = BasicController.extend({
.toggleClass('btn-default', createMuted);
}
},
- /**
- * @override
- * @param {Object} state
- * @returns {Deferred}
- */
- _update: function (state) {
- var hasNoContent = !this._hasContent(state);
- this.$el.toggleClass('o_kanban_nocontent', hasNoContent);
- this._toggleNoContentHelper(hasNoContent);
- return this._super.apply(this, arguments);
- },
//--------------------------------------------------------------------------
// Handlers
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 ea2f0270017..0bbc7aa2698 100644
--- a/addons/web/static/src/js/views/kanban/kanban_renderer.js
+++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js
@@ -100,6 +100,8 @@ var KanbanRenderer = BasicRenderer.extend({
viewType: 'kanban',
});
this.columnOptions = _.extend({}, params.column_options, { qweb: this.qweb });
+
+ this._setState(state);
},
//--------------------------------------------------------------------------
@@ -167,12 +169,32 @@ var KanbanRenderer = BasicRenderer.extend({
record.update(recordState);
}
},
+ /**
+ * @override
+ */
+ updateState: function (state) {
+ this._setState(state);
+ return this._super.apply(this, arguments);
+ },
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
+ * The nocontent helper should be displayed in kanban:
+ * - ungrouped: if there is no records
+ * - grouped: if there is no groups and no column quick create
+ *
+ * @override
+ * @private
+ */
+ _hasContent: function () {
+ return this._super.apply(this, arguments) ||
+ this.createColumnEnabled ||
+ (this.state.groupedBy.length && this.state.data.length);
+ },
+ /**
* Renders empty invisible divs in a document fragment.
*
* @private
@@ -193,28 +215,6 @@ var KanbanRenderer = BasicRenderer.extend({
*/
_renderGrouped: function (fragment) {
var self = this;
- var groupByFieldAttrs = this.state.fields[this.state.groupedBy[0]];
- var groupByFieldInfo = this.state.fieldsInfo.kanban[this.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
- var draggable = true;
- if (groupByFieldAttrs) {
- if (groupByFieldAttrs.type === "date" || groupByFieldAttrs.type === "datetime") {
- draggable = false;
- } else if (groupByFieldAttrs.readonly !== undefined) {
- draggable = !(groupByFieldAttrs.readonly);
- }
- }
- var groupedByM2O = groupByFieldAttrs && (groupByFieldAttrs.type === 'many2one');
- var grouped_by_field = groupedByM2O && groupByFieldAttrs.relation;
- var groupByTooltip = groupByFieldInfo && groupByFieldInfo.options.group_by_tooltip;
- this.columnOptions = _.extend(this.columnOptions, {
- draggable: draggable,
- group_by_tooltip: groupByTooltip,
- grouped_by_m2o: groupedByM2O,
- relation: grouped_by_field,
- });
// Render columns
_.each(this.state.data, function (group) {
@@ -228,7 +228,7 @@ var KanbanRenderer = BasicRenderer.extend({
}
});
- if (groupedByM2O) {
+ if (this.groupedByM2O) {
// Enable column sorting
this.$el.sortable({
axis: 'x',
@@ -249,7 +249,7 @@ var KanbanRenderer = BasicRenderer.extend({
});
// Enable column quickcreate
- if (this.columnOptions.group_creatable) {
+ if (this.createColumnEnabled) {
this.quickCreate = new ColumnQuickCreate(this);
this.quickCreate.appendTo(fragment);
}
@@ -280,20 +280,62 @@ var KanbanRenderer = BasicRenderer.extend({
_renderView: function () {
var oldWidgets = this.widgets;
this.widgets = [];
- var isGrouped = !!this.state.groupedBy.length;
- this.$el.toggleClass('o_kanban_grouped', isGrouped);
- this.$el.toggleClass('o_kanban_ungrouped', !isGrouped);
this.$el.empty();
- var fragment = document.createDocumentFragment();
- if (isGrouped) {
- this._renderGrouped(fragment);
+ var displayNoContentHelper = !this._hasContent() && !!this.noContentHelp;
+ this.$el.toggleClass('o_kanban_nocontent', displayNoContentHelper);
+ if (displayNoContentHelper) {
+ // display the no content helper if there is no data to display
+ this._renderNoContentHelper();
} else {
- this._renderUngrouped(fragment);
+ var isGrouped = !!this.state.groupedBy.length;
+ this.$el.toggleClass('o_kanban_grouped', isGrouped);
+ this.$el.toggleClass('o_kanban_ungrouped', !isGrouped);
+ var fragment = document.createDocumentFragment();
+ // render the kanban view
+ if (isGrouped) {
+ this._renderGrouped(fragment);
+ } else {
+ this._renderUngrouped(fragment);
+ }
+ this.$el.append(fragment);
}
- this.$el.append(fragment);
+
return this._super.apply(this, arguments).then(_.invoke.bind(_, oldWidgets, 'destroy'));
},
+ /**
+ * Sets the current state and updates some internal attributes accordingly.
+ *
+ * @private
+ * @param {Object} state
+ */
+ _setState: function (state) {
+ this.state = state;
+
+ var groupByFieldAttrs = state.fields[state.groupedBy[0]];
+ 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
+ var draggable = true;
+ if (groupByFieldAttrs) {
+ if (groupByFieldAttrs.type === "date" || groupByFieldAttrs.type === "datetime") {
+ draggable = false;
+ } else if (groupByFieldAttrs.readonly !== undefined) {
+ draggable = !(groupByFieldAttrs.readonly);
+ }
+ }
+ this.groupedByM2O = groupByFieldAttrs && (groupByFieldAttrs.type === 'many2one');
+ var grouped_by_field = this.groupedByM2O && groupByFieldAttrs.relation;
+ var groupByTooltip = groupByFieldInfo && groupByFieldInfo.options.group_by_tooltip;
+ this.columnOptions = _.extend(this.columnOptions, {
+ draggable: draggable,
+ group_by_tooltip: groupByTooltip,
+ grouped_by_m2o: this.groupedByM2O,
+ relation: grouped_by_field,
+ });
+ this.createColumnEnabled = this.groupedByM2O && this.columnOptions.group_creatable;
+ },
});
return KanbanRenderer;
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 2ec9cf3181e..3b74f140e4d 100644
--- a/addons/web/static/src/js/views/list/list_controller.js
+++ b/addons/web/static/src/js/views/list/list_controller.js
@@ -188,7 +188,6 @@ var ListController = BasicController.extend({
position: self.editable,
});
}).then(function (recordID) {
- self._toggleNoContentHelper(false);
var state = self.model.get(self.handle);
self.renderer.updateState(state, {});
self.renderer.editRecord(recordID);
@@ -283,12 +282,10 @@ var ListController = BasicController.extend({
},
/**
* @override
- * @param {Object} state
* @returns {Deferred}
*/
- _update: function (state) {
+ _update: function () {
this.selectedRecords = [];
- this._toggleNoContentHelper(!this._hasContent(state));
this._toggleSidebar();
return this._super.apply(this, arguments);
},
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 802f2f03a09..295266db276 100644
--- a/addons/web/static/src/js/views/list/list_renderer.js
+++ b/addons/web/static/src/js/views/list/list_renderer.js
@@ -30,7 +30,6 @@ var FIELD_CLASSES = {
};
var ListRenderer = BasicRenderer.extend({
- className: 'table-responsive',
events: {
'click tbody tr': '_onRowClicked',
'click tbody .o_list_record_selector': '_onSelectRecord',
@@ -577,12 +576,24 @@ var ListRenderer = BasicRenderer.extend({
_renderView: function () {
var self = this;
+ this.$el
+ .removeClass('table-responsive')
+ .empty();
+
// destroy the previously instantiated pagers, if any
_.invoke(this.pagers, 'destroy');
this.pagers = [];
+ // display the no content helper if there is no data to display
+ if (!this._hasContent() && this.noContentHelp) {
+ this._renderNoContentHelper();
+ return this._super();
+ }
+
var $table = $('<table>').addClass('o_list_view table table-condensed table-striped');
- this.$el.empty().append($table);
+ this.$el
+ .addClass('table-responsive')
+ .append($table);
var is_grouped = !!this.state.groupedBy.length;
this._computeAggregates();
$table.toggleClass('o_list_view_grouped', is_grouped);
diff --git a/addons/web/static/src/js/views/pivot/pivot_controller.js b/addons/web/static/src/js/views/pivot/pivot_controller.js
index 78640a97124..731183e7efe 100644
--- a/addons/web/static/src/js/views/pivot/pivot_controller.js
+++ b/addons/web/static/src/js/views/pivot/pivot_controller.js
@@ -170,21 +170,8 @@ var PivotController = AbstractController.extend({
/**
* @private
*/
- _update: function (state) {
+ _update: function () {
this._updateButtons();
- var hasNoContent = !state.has_data || !state.measures.length;
-
- if (hasNoContent) {
- if (!this.$('.oe_view_nocontent').length) {
- this.renderer.$el.detach();
- this.$el.append(QWeb.render('PivotView.nodata'));
- }
- } else {
- if (!document.contains(this.renderer.el)) {
- this.$('div.oe_view_nocontent').remove();
- this.$el.append(this.renderer.$el);
- }
- }
return this._super.apply(this, arguments);
},
/**
diff --git a/addons/web/static/src/js/views/pivot/pivot_renderer.js b/addons/web/static/src/js/views/pivot/pivot_renderer.js
index a37e65b104b..d279d59d4b1 100644
--- a/addons/web/static/src/js/views/pivot/pivot_renderer.js
+++ b/addons/web/static/src/js/views/pivot/pivot_renderer.js
@@ -2,8 +2,11 @@ odoo.define('web.PivotRenderer', function (require) {
"use strict";
var AbstractRenderer = require('web.AbstractRenderer');
+var core = require('web.core');
var field_utils = require('web.field_utils');
+var QWeb = core.qweb;
+
var PivotRenderer = AbstractRenderer.extend({
tagName: 'table',
className: 'table-hover table-condensed table-bordered',
@@ -16,14 +19,31 @@ var PivotRenderer = AbstractRenderer.extend({
//--------------------------------------------------------------------------
/**
+ * Used to determine whether or not to display the no content helper.
+ *
+ * @private
+ * @returns {boolean}
+ */
+ _hasContent: function () {
+ return this.state.has_data && this.state.measures.length;
+ },
+ /**
* @override
* @private
* @returns {Deferred}
*/
_render: function () {
- if (!this.state.has_data) {
+ if (!this._hasContent()) {
+ // display the nocontent helper
+ this.replaceElement(QWeb.render('PivotView.nodata'));
return this._super.apply(this, arguments);
}
+
+ if (!this.$el.is('table')) {
+ // coming from the no content helper, so the root element has to be
+ // re-rendered before rendering and appending its content
+ this.renderElement();
+ }
var $fragment = $(document.createDocumentFragment());
var $table = $('<table>').appendTo($fragment);
var $thead = $('<thead>').appendTo($table);