odoo.define('web.ViewManager', function (require) { "use strict"; var core = require('web.core'); var data = require('web.data'); 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 utils = require('web.utils'); var SearchView = require('web.SearchView'); var session = require('web.session'); var Widget = require('web.Widget'); var _t = core._t; var QWeb = core.qweb; var ViewManager = Widget.extend({ template: "ViewManager", /** * @param {Object} [dataset] null object (... historical reasons) * @param {Array} [views] List of [view_id, view_type] * @param {Object} [flags] various boolean describing UI state */ init: function(parent, dataset, views, flags, action) { if (action) { flags = action.flags || {}; if (!('auto_search' in flags)) { flags.auto_search = action.auto_search !== false; } if (action.res_model === 'board.board' && action.view_mode === 'form') { action.target = 'inline'; // Special case for Dashboards _.extend(flags, { views_switcher : false, display_title : false, search_view : false, pager : false, sidebar : false, action_buttons : false }); } 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); dataset.index = 0; } views = action.views; } var self = this; this._super(parent); 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; _.each(views, function (view) { var view_type = view[1] || view.view_type, View = core.view_registry.get(view_type, true), view_label = View ? View.prototype.display_name: (void 'nope'), view_descr = { controller: null, options: view.options || {}, view_id: view[0] || view.view_id, type: view_type, label: view_label, embedded_view: view.embedded_view, title: self.action && self.action.name, 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); }, /** * @returns {jQuery.Deferred} initial view loading promise */ start: function() { var self = this; var default_view = this.flags.default_view || this.view_order[0].type, 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(); var main_view_loaded = this.switch_mode(default_view, null, default_options); return $.when(main_view_loaded, this.search_view_loaded); }, switch_mode: function(view_type, no_store, view_options) { var self = this, view = this.views[view_type]; if (!view) { return $.Deferred().reject(); } 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) if (this.active_view && this.active_view !== view) { 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; 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(); } self.update_header(); return $.when(view.created, this.active_search).done(function () { self.active_view = view; 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(); }); }, 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 = $('
').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 = $('