summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
authorAaron Bohy <aab@odoo.com>2015-01-21 16:36:23 +0100
committerAaron Bohy <aab@odoo.com>2015-03-20 16:17:06 +0100
commit53a9f6c081d0d91c99d8f035fd09d813a16172e8 (patch)
treea4da311c1bda804c4800b4b272a316320ef9c25b /addons/web/static/src/js
parentdb592efca282d12f6fcef38a13dc2cbff31522b8 (diff)
[IMP] Web et al.: ControlPanel extracted from ViewManager
The ControlPanel is still instantiated by the ViewManager. Changes details: * web: views.js: Code related to views header is extracted from the ViewManager to a new Widget named ControlPanel. Also uses the headless flag to tell the inner view not to put its buttons (use case: kanban) or pager (use case: list) in the header as it is hidden. * web: view_form.js, base.xml: Uses the headless flag at initialization of the One2ManyViewManager widget instead of extending the ViewManager template (which doesn't handle the header anymore). * web: view_list.js: Test on this.options.$pager instead of this.options.$buttons when dealing with pager. Note: the behavior for list view is unchanged and has a bug. If there are more then 80 records to display, only the 80th first are display, and as there is no pager, there is no way to see the remaining ones. A fix for this would be to use a light ControlPanel in One2Many views as well. With this, there won't be duplicated .oe-'view'-buttons/sidebar/pager anymore. * web: view_graph.js, view_pivot.js: Only render buttons in non-headless mode * web_dashboard: dashboard.js: Fix some references that were broken with ControlPanel extraction * web_view_editor: web_view_editor.js: Extend ControlPanel instead of ViewManager * Changes in selector of ControlPanel elements in several addons: * base_import * mail * web
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/action_manager.js3
-rw-r--r--addons/web/static/src/js/control_panel.js375
-rw-r--r--addons/web/static/src/js/view_manager.js358
-rw-r--r--addons/web/static/src/js/views/form_relational_widgets.js5
-rw-r--r--addons/web/static/src/js/views/graph_view.js15
-rw-r--r--addons/web/static/src/js/views/list_view.js2
-rw-r--r--addons/web/static/src/js/views/pivot_view.js17
7 files changed, 439 insertions, 336 deletions
diff --git a/addons/web/static/src/js/action_manager.js b/addons/web/static/src/js/action_manager.js
index efc617c4af2..61686dc4e7e 100644
--- a/addons/web/static/src/js/action_manager.js
+++ b/addons/web/static/src/js/action_manager.js
@@ -142,9 +142,6 @@ var ActionManager = Widget.extend({
w.destroy();
});
self.inner_widget = _.last(self.widgets);
- if (self.inner_widget.display_breadcrumbs) {
- self.inner_widget.display_breadcrumbs();
- }
if (self.inner_widget.do_show) {
self.inner_widget.do_show();
}
diff --git a/addons/web/static/src/js/control_panel.js b/addons/web/static/src/js/control_panel.js
new file mode 100644
index 00000000000..d5c016522f5
--- /dev/null
+++ b/addons/web/static/src/js/control_panel.js
@@ -0,0 +1,375 @@
+odoo.define('web.ControlPanel', function (require) {
+"use strict";
+
+var core = require('web.core');
+var Dialog = require('web.Dialog');
+var formats = require('web.formats');
+var framework = require('web.framework');
+var Model = require('web.Model');
+var pyeval = require('web.pyeval');
+var SearchView = require('web.SearchView');
+var utils = require('web.utils');
+var Widget = require('web.Widget');
+
+var ControlPanel = Widget.extend({
+ template: 'ControlPanel',
+ events: {
+ "click .oe_debug_view": "on_debug_changed",
+ "click .oe-cp-switch-buttons button": "on_switch_buttons_click",
+ },
+ /**
+ * @param {String} [template] the QWeb template to render the ControlPanel.
+ * By default, the template 'ControlPanel' will be used
+ */
+ init: function(parent, template) {
+ this._super(parent);
+ if (template) {
+ this.template = template;
+ }
+
+ this.view_manager = parent;
+ this.action_manager = this.view_manager.action_manager;
+ this.action = this.view_manager.action;
+ this.dataset = this.view_manager.dataset;
+ this.active_view = this.view_manager.active_view;
+ this.views = this.view_manager.views;
+ this.flags = this.view_manager.flags;
+ this.title = this.view_manager.title; // needed for Favorites of searchview
+ this.view_order = this.view_manager.view_order;
+ this.multiple_views = (this.view_order.length > 1);
+ },
+ start: function() {
+ var self = this;
+
+ // Retrieve control panel elements
+ this.$control_panel = this.$('.oe-control-panel-content');
+ this.$breadcrumbs = this.$('.oe-view-title');
+ this.$switch_buttons = this.$('.oe-cp-switch-buttons button');
+ this.$title_col = this.$control_panel.find('.oe-cp-title');
+ this.$search_col = this.$control_panel.find('.oe-cp-search-view');
+ // AAB: Use sidebar and pager of the ControlPanel only if it is displayed, otherwise set them
+ // to undefined to that the view uses its own elements to sidebar and pager, as follows:
+ // this.$sidebar = !this.flags.headless && this.flags.sidebar ? this.$('.oe-cp-sidebar') : undefined,
+ // this.$pager = !this.flags.headless ? this.$('.oe-cp-pager') : undefined;
+ // But rather use the following definition to keep behavior as it is for now (i.e. it does not
+ // display the pager in one2many list views)
+ this.$sidebar = this.flags.sidebar ? this.$('.oe-cp-sidebar') : undefined;
+ this.$pager = this.$('.oe-cp-pager');
+
+ // Hide the ControlPanel in headless mode
+ if (this.flags.headless) {
+ this.$control_panel.hide();
+ }
+
+ _.each(this.views, function (view) {
+ // Expose control panel elements to the views so that they can insert stuff in them
+ view.options = _.extend(view.options, {
+ $buttons : !self.flags.headless ? self.$('.oe-' + view.type + '-buttons') : undefined,
+ $sidebar : self.$sidebar,
+ $pager : self.$pager,
+ }, self.flags, self.flags[view.type], view.options);
+ // Show $buttons as views will put their own buttons inside it and show/hide them
+ if (view.options.$buttons) view.options.$buttons.show();
+ self.$('.oe-cp-switch-' + view.type).tooltip();
+ });
+
+ // Create the searchview
+ this.search_view_loaded = this.setup_search_view();
+
+ return this._super();
+ },
+ /**
+ * Triggers an event when switch-buttons are clicked on
+ */
+ on_switch_buttons_click: function(event) {
+ var view_type = $(event.target).data('view-type');
+ this.trigger('switch_view', view_type);
+ },
+ /**
+ * Updates its status according to the active_view
+ */
+ update: function(active_view) {
+ this.active_view = active_view;
+
+ this.update_search_view();
+ this.update_breadcrumbs();
+ this.render_debug_view();
+
+ // Update switch-buttons
+ this.$switch_buttons.removeClass('active');
+ this.$('.oe-cp-switch-' + this.active_view.type).addClass('active');
+ },
+ update_breadcrumbs: function () {
+ var self = this;
+ if (!this.action_manager) return;
+ var breadcrumbs = this.action_manager.get_breadcrumbs();
+ if (!breadcrumbs.length) return;
+
+ var $breadcrumbs = breadcrumbs.map(function (bc, index) {
+ return make_breadcrumb(bc, index === breadcrumbs.length - 1);
+ });
+
+ this.$breadcrumbs
+ .empty()
+ .append($breadcrumbs);
+
+ function make_breadcrumb (bc, is_last) {
+ var $bc = $('<li>')
+ .append(is_last ? bc.title : $('<a>').text(bc.title))
+ .toggleClass('active', is_last);
+ if (!is_last) {
+ $bc.click(function () {
+ self.action_manager.select_widget(bc.widget, bc.index);
+ });
+ }
+ return $bc;
+ }
+ },
+ /**
+ * Sets up the search view.
+ *
+ * @returns {jQuery.Deferred} search view startup deferred
+ */
+ setup_search_view: function() {
+ if (this.searchview) {
+ this.searchview.destroy();
+ }
+
+ var view_id = (this.action && this.action.search_view_id && this.action.search_view_id[0]) || false;
+
+ var search_defaults = {};
+
+ var context = this.action ? this.action.context : [];
+ _.each(context, function (value, key) {
+ var match = /^search_default_(.*)$/.exec(key);
+ if (match) {
+ search_defaults[match[1]] = value;
+ }
+ });
+
+ var options = {
+ hidden: this.flags.search_view === false,
+ disable_custom_filters: this.flags.search_disable_custom_filters,
+ $buttons: this.$('.oe-search-options'),
+ action: this.action,
+ };
+ this.searchview = new SearchView(this, this.dataset, view_id, search_defaults, options);
+
+ this.searchview.on('search_data', this, this.search.bind(this));
+ return this.searchview.appendTo(this.$(".oe-cp-search-view:first"));
+ },
+ update_search_view: function() {
+ if (this.searchview) {
+ var is_hidden = this.active_view.controller.searchable === false;
+ this.searchview.toggle_visibility(!is_hidden);
+ this.$title_col.toggleClass('col-md-6', !is_hidden).toggleClass('col-md-12', is_hidden);
+ this.$search_col.toggle(!is_hidden);
+ }
+ },
+ search: function(domains, contexts, groupbys) {
+ var self = this,
+ controller = this.active_view.controller,
+ action_context = this.action.context || {},
+ view_context = controller.get_context();
+ pyeval.eval_domains_and_contexts({
+ domains: [this.action.domain || []].concat(domains || []),
+ contexts: [action_context, view_context].concat(contexts || []),
+ group_by_seq: groupbys || []
+ }).done(function (results) {
+ if (results.error) {
+ self.active_search.resolve();
+ throw new Error(
+ _.str.sprintf(_t("Failed to evaluate search criterions")+": \n%s",
+ JSON.stringify(results.error)));
+ }
+ self.dataset._model = new Model(
+ self.dataset.model, results.context, results.domain);
+ var groupby = results.group_by.length ?
+ results.group_by :
+ action_context.group_by;
+ if (_.isString(groupby)) {
+ groupby = [groupby];
+ }
+ if (!controller.grouped && !_.isEmpty(groupby)){
+ self.dataset.set_sort([]);
+ }
+ $.when(controller.do_search(results.domain, results.context, groupby || [])).then(function() {
+ self.active_search.resolve();
+ });
+ });
+ },
+ activate_search: function(view_created_def) {
+ this.active_search = $.Deferred();
+ if (this.searchview &&
+ this.flags.auto_search &&
+ this.active_view.controller.searchable !== false) {
+ $.when(this.search_view_loaded,view_created_def).done(this.searchview.do_search);
+ } else {
+ this.active_search.resolve();
+ }
+ return this.active_search;
+ },
+ on_debug_changed: function (evt) {
+ var self = this,
+ params = $(evt.target).data(),
+ val = params.action,
+ current_view = this.active_view.controller;
+ switch (val) {
+ case 'fvg':
+ var dialog = new Dialog(this, { title: _t("Fields View Get") }).open();
+ $('<pre>').text(utils.json_node_to_xml(current_view.fields_view.arch, true)).appendTo(dialog.$el);
+ break;
+ case 'tests':
+ this.do_action({
+ name: _t("JS Tests"),
+ target: 'new',
+ type : 'ir.actions.act_url',
+ url: '/web/tests?mod=*'
+ });
+ break;
+ case 'get_metadata':
+ var ids = current_view.get_selected_ids();
+ if (ids.length === 1) {
+ this.dataset.call('get_metadata', [ids]).done(function(result) {
+ var dialog = new Dialog(this, {
+ title: _.str.sprintf(_t("Metadata (%s)"), self.dataset.model),
+ size: 'medium',
+ buttons: {
+ Ok: function() { this.parents('.modal').modal('hide');}
+ },
+ }, QWeb.render('ViewManagerDebugViewLog', {
+ perm : result[0],
+ format : formats.format_value
+ })).open();
+ });
+ }
+ break;
+ case 'toggle_layout_outline':
+ current_view.rendering_engine.toggle_layout_debugging();
+ break;
+ case 'set_defaults':
+ current_view.open_defaults_dialog();
+ break;
+ case 'translate':
+ this.do_action({
+ name: _t("Technical Translation"),
+ res_model : 'ir.translation',
+ domain : [['type', '!=', 'object'], '|', ['name', '=', this.dataset.model], ['name', 'ilike', this.dataset.model + ',']],
+ views: [[false, 'list'], [false, 'form']],
+ type : 'ir.actions.act_window',
+ view_type : "list",
+ view_mode : "list"
+ });
+ break;
+ case 'fields':
+ this.dataset.call('fields_get', [false, {}]).done(function (fields) {
+ var $root = $('<dl>');
+ _(fields).each(function (attributes, name) {
+ $root.append($('<dt>').append($('<h4>').text(name)));
+ var $attrs = $('<dl>').appendTo($('<dd>').appendTo($root));
+ _(attributes).each(function (def, name) {
+ if (def instanceof Object) {
+ def = JSON.stringify(def);
+ }
+ $attrs
+ .append($('<dt>').text(name))
+ .append($('<dd style="white-space: pre-wrap;">').text(def));
+ });
+ });
+ new Dialog(self, {
+ title: _.str.sprintf(_t("Model %s fields"),
+ self.dataset.model),
+ buttons: {
+ Ok: function() { this.parents('.modal').modal('hide');}
+ },
+ }, $root).open();
+ });
+ break;
+ case 'edit_workflow':
+ return this.do_action({
+ res_model : 'workflow',
+ name: _t('Edit Workflow'),
+ domain : [['osv', '=', this.dataset.model]],
+ views: [[false, 'list'], [false, 'form'], [false, 'diagram']],
+ type : 'ir.actions.act_window',
+ view_type : 'list',
+ view_mode : 'list'
+ });
+ case 'edit':
+ this.do_edit_resource(params.model, params.id, evt.target.text);
+ break;
+ case 'manage_filters':
+ this.do_action({
+ res_model: 'ir.filters',
+ name: _t('Manage Filters'),
+ views: [[false, 'list'], [false, 'form']],
+ type: 'ir.actions.act_window',
+ context: {
+ search_default_my_filters: true,
+ search_default_model_id: this.dataset.model
+ }
+ });
+ break;
+ case 'print_workflow':
+ if (current_view.get_selected_ids && current_view.get_selected_ids().length == 1) {
+ framework.blockUI();
+ var action = {
+ context: { active_ids: current_view.get_selected_ids() },
+ report_name: "workflow.instance.graph",
+ datas: {
+ model: this.dataset.model,
+ id: current_view.get_selected_ids()[0],
+ nested: true,
+ }
+ };
+ this.session.get_file({
+ url: '/web/report',
+ data: {action: JSON.stringify(action)},
+ complete: framework.unblockUI
+ });
+ } else {
+ self.do_warn("Warning", "No record selected.");
+ }
+ break;
+ case 'leave_debug':
+ window.location.search="?";
+ break;
+ default:
+ if (val) {
+ console.warn("No debug handler for ", val);
+ }
+ }
+ },
+ do_edit_resource: function(model, id, name) {
+ this.do_action({
+ res_model : model,
+ res_id : id,
+ name: name,
+ type : 'ir.actions.act_window',
+ view_type : 'form',
+ view_mode : 'form',
+ views : [[false, 'form']],
+ target : 'new',
+ flags : {
+ action_buttons : true,
+ headless: true,
+ }
+ });
+ },
+ /**
+ * Renders the debug dropdown according to the active_view
+ */
+ render_debug_view: function() {
+ var self = this;
+ if (self.session.debug) {
+ self.$('.oe_debug_view').html(QWeb.render('ViewManagerDebug', {
+ view: self.active_view.controller,
+ widget: self,
+ }));
+ }
+ },
+});
+
+return ControlPanel;
+
+});
diff --git a/addons/web/static/src/js/view_manager.js b/addons/web/static/src/js/view_manager.js
index 869ba4f1b0c..0474f0e127b 100644
--- a/addons/web/static/src/js/view_manager.js
+++ b/addons/web/static/src/js/view_manager.js
@@ -1,6 +1,7 @@
odoo.define('web.ViewManager', function (require) {
"use strict";
+var ControlPanel = require('web.ControlPanel');
var core = require('web.core');
var data = require('web.data');
var Dialog = require('web.Dialog');
@@ -43,7 +44,6 @@ var ViewManager = Widget.extend({
}
this.action = action;
this.action_manager = parent;
- this.debug = session.debug;
dataset = new data.DataSetSearch(this, action.res_model, action.context, action.domain);
if (action.res_id) {
dataset.ids.push(action.res_id);
@@ -57,12 +57,9 @@ var ViewManager = Widget.extend({
this.flags = flags || {};
this.dataset = dataset;
this.view_order = [];
- this.url_states = {};
this.views = {};
this.view_stack = []; // used for breadcrumbs
this.active_view = null;
- this.searchview = null;
- this.active_search = null;
this.registry = core.view_registry;
this.title = this.action && this.action.name;
@@ -77,68 +74,61 @@ var ViewManager = Widget.extend({
type: view_type,
label: view_label,
embedded_view: view.embedded_view,
- title: self.action && self.action.name,
+ title: self.title,
button_label: View ? _.str.sprintf(_t('%(view_type)s view'), {'view_type': (view_label || view_type)}) : (void 'nope'),
};
self.view_order.push(view_descr);
self.views[view_type] = view_descr;
});
- this.multiple_views = (self.view_order.length > 1);
+
+ // Instantiate ControlPanel
+ this.control_panel = new ControlPanel(self);
+ // Listen to event 'switch_view' trigerred when clicking on switch-buttons
+ this.control_panel.on('switch_view', this, function(view_type) {
+ if (view_type === 'form' && this.active_view && this.active_view.type === 'form') {
+ this._display_view(view_type);
+ } else {
+ this.switch_mode(view_type);
+ }
+ });
},
/**
* @returns {jQuery.Deferred} initial view loading promise
*/
start: function() {
var self = this;
- var default_view = this.flags.default_view || this.view_order[0].type,
+ var default_view = this.get_default_view(),
default_options = this.flags[default_view] && this.flags[default_view].options;
- if (this.flags.headless) {
- this.$('.oe-view-manager-header').hide();
- }
this._super();
- var $sidebar = this.flags.sidebar ? this.$('.oe-view-manager-sidebar') : undefined,
- $pager = this.$('.oe-view-manager-pager');
- this.$breadcrumbs = this.$('.oe-view-title');
- this.$switch_buttons = this.$('.oe-view-manager-switch button');
- this.$header = this.$('.oe-view-manager-header');
- this.$header_col = this.$header.find('.oe-header-title');
- this.$search_col = this.$header.find('.oe-view-manager-search-view');
- this.$switch_buttons.click(function (event) {
- var view_type = $(this).data('view-type');
- if ((view_type === 'form') && (self.active_view.type === 'form')) {
- self._display_view(view_type);
- } else {
- self.switch_mode(view_type);
- }
- });
var views_ids = {};
_.each(this.views, function (view) {
views_ids[view.type] = view.view_id;
view.options = _.extend({
- $buttons: self.$('.oe-' + view.type + '-buttons'),
- $sidebar : $sidebar,
- $pager : $pager,
action : self.action,
action_views_ids : views_ids,
}, self.flags, self.flags[view.type], view.options);
view.$container = self.$(".oe-view-manager-view-" + view.type);
-
- // show options.$buttons as views will put their $buttons inside it
- // and call show/hide on them
- view.options.$buttons.show();
- self.$('.oe-vm-switch-' + view.type).tooltip();
});
- this.$('.oe_debug_view').click(this.on_debug_changed);
+
this.$el.addClass("oe_view_manager_" + ((this.action && this.action.target) || 'current'));
- this.search_view_loaded = this.setup_search_view();
+ // Insert ControlPanel in the DOM
+ var cp_loaded = this.control_panel.prependTo(this.$el);
var main_view_loaded = this.switch_mode(default_view, null, default_options);
- return $.when(main_view_loaded, this.search_view_loaded);
+ return $.when(main_view_loaded, cp_loaded);
+ },
+ /**
+ * Needed for dashboard.js to add Favorites to Dashboard
+ */
+ get_searchview: function() {
+ return this.control_panel.searchview;
+ },
+ get_default_view: function() {
+ return this.flags.default_view || this.view_order[0].type;
},
-
switch_mode: function(view_type, no_store, view_options) {
var self = this,
view = this.views[view_type];
@@ -148,7 +138,8 @@ var ViewManager = Widget.extend({
}
if ((view_type !== 'form') && (view_type !== 'diagram')) {
this.view_stack = [];
- }
+ }
+
this.view_stack.push(view);
// Hide active view (at first rendering, there is no view to hide)
@@ -156,86 +147,35 @@ var ViewManager = Widget.extend({
if (this.active_view.controller) this.active_view.controller.do_hide();
if (this.active_view.$container) this.active_view.$container.hide();
}
- this.active_view = view;
+ this.active_view = this.control_panel.active_view = view;
if (!view.created) {
view.created = this.create_view.bind(this)(view, view_options);
}
- this.active_search = $.Deferred();
-
- if (this.searchview &&
- this.flags.auto_search &&
- view.controller.searchable !== false) {
- $.when(this.search_view_loaded, view.created).done(this.searchview.do_search);
- } else {
- this.active_search.resolve();
- }
+ // Tell the ControlPanel to call do_search on its searchview
+ var active_search = this.control_panel.activate_search(view.created);
- self.update_header();
- return $.when(view.created, this.active_search).done(function () {
- self.active_view = view;
+ return $.when(view.created, active_search).done(function () {
self._display_view(view_options);
self.trigger('switch_mode', view_type, no_store, view_options);
- if (self.debug) {
- self.$('.oe_debug_view').html(QWeb.render('ViewManagerDebug', {
- view: self.active_view.controller,
- view_manager: self,
- uid: session.uid,
- }));
- }
});
},
- update_header: function () {
- this.$switch_buttons.removeClass('active');
- this.$('.oe-vm-switch-' + this.active_view.type).addClass('active');
- },
_display_view: function (view_options) {
var self = this;
this.active_view.$container.show();
$.when(this.active_view.controller.do_show(view_options)).done(function () {
- if (self.searchview) {
- var is_hidden = self.active_view.controller.searchable === false;
- self.searchview.toggle_visibility(!is_hidden);
- self.$header_col.toggleClass('col-md-6', !is_hidden).toggleClass('col-md-12', is_hidden);
- self.$search_col.toggle(!is_hidden);
- }
- self.display_breadcrumbs();
+ // Tell the ControlPanel to update its elemnts
+ self.control_panel.update(self.active_view);
});
},
- display_breadcrumbs: function () {
- var self = this;
- if (!this.action_manager) return;
- var breadcrumbs = this.action_manager.get_breadcrumbs();
- if (!breadcrumbs.length) return;
-
- var $breadcrumbs = breadcrumbs.map(function (bc, index) {
- return make_breadcrumb(bc, index === breadcrumbs.length - 1);
- });
-
- this.$breadcrumbs
- .empty()
- .append($breadcrumbs);
-
- function make_breadcrumb (bc, is_last) {
- var $bc = $('<li>')
- .append(is_last ? bc.title : $('<a>').text(bc.title))
- .toggleClass('active', is_last);
- if (!is_last) {
- $bc.click(function () {
- self.action_manager.select_widget(bc.widget, bc.index);
- });
- }
- return $bc;
- }
- },
create_view: function(view, view_options) {
var self = this,
- View = this.registry.get(view.type),
+ View = this.registry.get_object(view.type),
options = _.clone(view.options),
view_loaded = $.Deferred();
- if (view.type === "form" && ((this.action && (this.action.target === 'new' || this.action.target === 'inline'))
- || (view_options && view_options.mode === 'edit'))) {
+ if (view.type === "form" && ((this.action && (this.action.target === 'new' || this.action.target === 'inline')) ||
+ (view_options && view_options.mode === 'edit'))) {
options.initial_mode = 'edit';
}
var controller = new View(this, this.dataset, view.view_id, options),
@@ -253,14 +193,13 @@ var ViewManager = Widget.extend({
if (self.action_manager) self.action_manager.trigger('history_back');
});
controller.on("change:title", this, function() {
- self.display_breadcrumbs();
+ self.control_panel.update_breadcrumbs();
});
controller.on('view_loaded', this, function () {
view_loaded.resolve();
});
- this.$('.oe-view-manager-pager > span').hide();
return $.when(controller.appendTo($container), view_loaded)
- .done(function () {
+ .done(function () {
self.trigger("controller_inited", view.type, controller);
});
},
@@ -275,73 +214,6 @@ var ViewManager = Widget.extend({
get_view_id: function(view_type) {
return this.views[view_type] && this.views[view_type].view_id || false;
},
- /**
- * Sets up the current viewmanager's search view.
- *
- * @param {Number|false} view_id the view to use or false for a default one
- * @returns {jQuery.Deferred} search view startup deferred
- */
- setup_search_view: function() {
- if (this.searchview) {
- this.searchview.destroy();
- }
-
- var view_id = (this.action && this.action.search_view_id && this.action.search_view_id[0]) || false;
-
- var search_defaults = {};
-
- var context = this.action ? this.action.context : [];
- _.each(context, function (value, key) {
- var match = /^search_default_(.*)$/.exec(key);
- if (match) {
- search_defaults[match[1]] = value;
- }
- });
-
-
- var options = {
- hidden: this.flags.search_view === false,
- disable_custom_filters: this.flags.search_disable_custom_filters,
- $buttons: this.$('.oe-search-options'),
- action: this.action,
- };
- this.searchview = new SearchView(this, this.dataset, view_id, search_defaults, options);
-
- this.searchview.on('search_data', this, this.search.bind(this));
- return this.searchview.appendTo(this.$(".oe-view-manager-search-view:first"));
- },
- search: function(domains, contexts, groupbys) {
- var self = this,
- controller = this.active_view.controller,
- action_context = this.action.context || {},
- view_context = controller.get_context();
- pyeval.eval_domains_and_contexts({
- domains: [this.action.domain || []].concat(domains || []),
- contexts: [action_context, view_context].concat(contexts || []),
- group_by_seq: groupbys || []
- }).done(function (results) {
- if (results.error) {
- self.active_search.resolve();
- throw new Error(
- _.str.sprintf(_t("Failed to evaluate search criterions")+": \n%s",
- JSON.stringify(results.error)));
- }
- self.dataset._model = new Model(
- self.dataset.model, results.context, results.domain);
- var groupby = results.group_by.length
- ? results.group_by
- : action_context.group_by;
- if (_.isString(groupby)) {
- groupby = [groupby];
- }
- if (!controller.grouped && !_.isEmpty(groupby)){
- self.dataset.set_sort([]);
- }
- $.when(controller.do_search(results.domain, results.context, groupby || [])).then(function() {
- self.active_search.resolve();
- });
- });
- },
do_push_state: function(state) {
if (this.action_manager) {
state.view_type = this.active_view.type;
@@ -356,156 +228,8 @@ var ViewManager = Widget.extend({
// on the new view, after it was initialized, but before it is fully loaded and
// in particular, before the do_show method is called.
this.switch_mode(state.view_type, true);
- }
- this.active_view.controller.do_load_state(state, warm);
- },
- on_debug_changed: function (evt) {
- var self = this,
- params = $(evt.target).data(),
- val = params.action,
- current_view = this.active_view.controller;
- switch (val) {
- case 'fvg':
- var dialog = new Dialog(this, { title: _t("Fields View Get") }).open();
- $('<pre>').text(utils.json_node_to_xml(current_view.fields_view.arch, true)).appendTo(dialog.$el);
- break;
- case 'tests':
- this.do_action({
- name: _t("JS Tests"),
- target: 'new',
- type : 'ir.actions.act_url',
- url: '/web/tests?mod=*'
- });
- break;
- case 'get_metadata':
- var ids = current_view.get_selected_ids();
- if (ids.length === 1) {
- this.dataset.call('get_metadata', [ids]).done(function(result) {
- var dialog = new Dialog(this, {
- title: _.str.sprintf(_t("Metadata (%s)"), self.dataset.model),
- size: 'medium',
- buttons: {
- Ok: function() { this.parents('.modal').modal('hide');}
- },
- }, QWeb.render('ViewManagerDebugViewLog', {
- perm : result[0],
- format : formats.format_value
- }));
- dialog.open();
- });
- }
- break;
- case 'toggle_layout_outline':
- current_view.rendering_engine.toggle_layout_debugging();
- break;
- case 'set_defaults':
- current_view.open_defaults_dialog();
- break;
- case 'translate':
- this.do_action({
- name: _t("Technical Translation"),
- res_model : 'ir.translation',
- domain : [['type', '!=', 'object'], '|', ['name', '=', this.dataset.model], ['name', 'ilike', this.dataset.model + ',']],
- views: [[false, 'list'], [false, 'form']],
- type : 'ir.actions.act_window',
- view_type : "list",
- view_mode : "list"
- });
- break;
- case 'fields':
- this.dataset.call('fields_get', [false, {}]).done(function (fields) {
- var $root = $('<dl>');
- _(fields).each(function (attributes, name) {
- $root.append($('<dt>').append($('<h4>').text(name)));
- var $attrs = $('<dl>').appendTo($('<dd>').appendTo($root));
- _(attributes).each(function (def, name) {
- if (def instanceof Object) {
- def = JSON.stringify(def);
- }
- $attrs
- .append($('<dt>').text(name))
- .append($('<dd style="white-space: pre-wrap;">').text(def));
- });
- });
- new Dialog(self, {
- title: _.str.sprintf(_t("Model %s fields"),
- self.dataset.model),
- buttons: {
- Ok: function() { this.parents('.modal').modal('hide');}
- },
- }, $root).open();
- });
- break;
- case 'edit_workflow':
- return this.do_action({
- res_model : 'workflow',
- name: _t('Edit Workflow'),
- domain : [['osv', '=', this.dataset.model]],
- views: [[false, 'list'], [false, 'form'], [false, 'diagram']],
- type : 'ir.actions.act_window',
- view_type : 'list',
- view_mode : 'list'
- });
- case 'edit':
- this.do_edit_resource(params.model, params.id, evt.target.text);
- break;
- case 'manage_filters':
- this.do_action({
- res_model: 'ir.filters',
- name: _t('Manage Filters'),
- views: [[false, 'list'], [false, 'form']],
- type: 'ir.actions.act_window',
- context: {
- search_default_my_filters: true,
- search_default_model_id: this.dataset.model
- }
- });
- break;
- case 'print_workflow':
- if (current_view.get_selected_ids && current_view.get_selected_ids().length == 1) {
- framework.blockUI();
- var action = {
- context: { active_ids: current_view.get_selected_ids() },
- report_name: "workflow.instance.graph",
- datas: {
- model: this.dataset.model,
- id: current_view.get_selected_ids()[0],
- nested: true,
- }
- };
- this.session.get_file({
- url: '/web/report',
- data: {action: JSON.stringify(action)},
- complete: framework.unblockUI
- });
- } else {
- self.do_warn("Warning", "No record selected.");
- }
- break;
- case 'leave_debug':
- window.location.search="?";
- break;
- default:
- if (val) {
- console.warn("No debug handler for ", val);
- }
}
- },
- do_edit_resource: function(model, id, name) {
- this.do_action({
- res_model : model,
- res_id : id,
- name: name,
- type : 'ir.actions.act_window',
- view_type : 'form',
- view_mode : 'form',
- views : [[false, 'form']],
- target : 'new',
- flags : {
- action_buttons : true,
- headless: true,
- }
- });
+ this.active_view.controller.do_load_state(state, warm);
},
});
diff --git a/addons/web/static/src/js/views/form_relational_widgets.js b/addons/web/static/src/js/views/form_relational_widgets.js
index 376a01f07f5..a33f1b84469 100644
--- a/addons/web/static/src/js/views/form_relational_widgets.js
+++ b/addons/web/static/src/js/views/form_relational_widgets.js
@@ -1078,9 +1078,10 @@ var One2ManyFormView = FormView.extend({
});
var One2ManyViewManager = ViewManager.extend({
- template: 'One2Many.viewmanager',
init: function(parent, dataset, views, flags) {
- this._super(parent, dataset, views, _.extend({}, flags, {$sidebar: false}));
+ // Only display the ControlPanel when there are several views to display
+ var flags = _.extend({}, flags, {$sidebar: false, headless: (views.length <= 1)});
+ this._super(parent, dataset, views, flags);
this.registry = core.view_registry.extend({
list: One2ManyListView,
form: One2ManyFormView,
diff --git a/addons/web/static/src/js/views/graph_view.js b/addons/web/static/src/js/views/graph_view.js
index f8e89a27e86..2ab42516ba2 100644
--- a/addons/web/static/src/js/views/graph_view.js
+++ b/addons/web/static/src/js/views/graph_view.js
@@ -34,12 +34,15 @@ var GraphView = View.extend({
return $.when(this._super(), load_fields).then(this.render_buttons.bind(this));
},
render_buttons: function () {
- var context = {measures: _.pairs(_.omit(this.measures, '__count__'))};
- this.$buttons.html(QWeb.render('GraphView.buttons', context));
- this.$measure_list = this.$buttons.find('.oe-measure-list');
- this.update_measure();
- this.$buttons.find('button').tooltip();
- this.$buttons.click(this.on_button_click.bind(this));
+ // Render buttons only in non-headless mode as buttons are in the header
+ if (!this.options.headless) {
+ var context = {measures: _.pairs(_.omit(this.measures, '__count__'))};
+ this.$buttons.html(QWeb.render('GraphView.buttons', context));
+ this.$measure_list = this.$buttons.find('.oe-measure-list');
+ this.update_measure();
+ this.$buttons.find('button').tooltip();
+ this.$buttons.click(this.on_button_click.bind(this));
+ }
},
update_measure: function () {
var self = this;
diff --git a/addons/web/static/src/js/views/list_view.js b/addons/web/static/src/js/views/list_view.js
index 93bf5b5071f..9207f17b610 100644
--- a/addons/web/static/src/js/views/list_view.js
+++ b/addons/web/static/src/js/views/list_view.js
@@ -304,7 +304,7 @@ var ListView = View.extend( /** @lends instance.web.ListView# */ {
// Pager
if (!this.$pager) {
this.$pager = $(QWeb.render("ListView.pager", {'widget':self})).hide();
- if (this.options.$buttons) {
+ if (this.options.$pager) {
this.$pager.appendTo(this.options.$pager);
} else {
this.$el.find('.oe_list_pager').replaceWith(this.$pager);
diff --git a/addons/web/static/src/js/views/pivot_view.js b/addons/web/static/src/js/views/pivot_view.js
index cd401b3ea51..05f84477cec 100644
--- a/addons/web/static/src/js/views/pivot_view.js
+++ b/addons/web/static/src/js/views/pivot_view.js
@@ -85,20 +85,23 @@ var PivotView = View.extend({
},
render_buttons: function () {
var self = this;
- var context = {measures: _.pairs(_.omit(this.measures, '__count__'))};
- this.$buttons.html(QWeb.render('PivotView.buttons', context));
- this.$buttons.click(this.on_button_click.bind(this));
- this.active_measures.forEach(function (measure) {
- self.$buttons.find('li[data-field="' + measure + '"]').addClass('selected');
- });
+ // Render buttons only in non-headless mode as buttons are in the header
+ if (!this.options.headless) {
+ var context = {measures: _.pairs(_.omit(this.measures, '__count__'))};
+ this.$buttons.html(QWeb.render('PivotView.buttons', context));
+ this.$buttons.click(this.on_button_click.bind(this));
+ this.active_measures.forEach(function (measure) {
+ self.$buttons.find('li[data-field="' + measure + '"]').addClass('selected');
+ });
+ this.$buttons.find('button').tooltip();
+ }
var another_ctx = {fields: _.chain(this.groupable_fields).pairs().sortBy(function(f){return f[1].string;}).value()};
this.$field_selection = this.$('.o-field-selection');
this.$field_selection.html(QWeb.render('PivotView.FieldSelection', another_ctx));
core.bus.on('click', self, function () {
self.$field_selection.find('ul').first().hide();
});
- this.$buttons.find('button').tooltip();
},
view_loading: function (fvg) {
var self = this;