summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views.js
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2014-10-07 16:27:43 +0200
committerGéry Debongnie <ged@odoo.com>2014-10-21 09:33:50 +0200
commitd8d6311b50d0d3446cab3f3386ad672ac486bab2 (patch)
tree177c5c1afe6cdcf44604d84e1d0014a540e0f80f /addons/web/static/src/js/views.js
parentbafa09f7e46201effdd36fe621f533b2ecda578d (diff)
[IMP] rewrite of search view/view manager
Second part of a large refactoring. Lots of cleanup, simpler code organization, and it should be faster.
Diffstat (limited to 'addons/web/static/src/js/views.js')
-rw-r--r--addons/web/static/src/js/views.js346
1 files changed, 258 insertions, 88 deletions
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index 88e62433adb..2659d46772f 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -19,9 +19,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
this.dialog = null;
this.dialog_widget = null;
this.view_managers = [];
- this.on('history_back', this, function() {
- return this.history_back();
- });
+ this.on('history_back', this, this.proxy('history_back'));
},
dialog_stop: function (reason) {
if (this.dialog) {
@@ -53,11 +51,20 @@ instance.web.ActionManager = instance.web.Widget.extend({
var to_destroy = this.view_managers;
this.view_managers = [];
}
- this.view_managers.push(widget);
+ if (widget instanceof instance.web.ViewManager) {
+ this.view_managers.push(widget);
+ } else {
+ this.view_managers.push({
+ view_stack: [{
+ controller: {get: function () {return action.display_name || action.name; }},
+ }],
+ destroy: function () {},
+ });
+ }
this.inner_action = action;
this.inner_widget = widget;
return $.when(this.inner_widget.appendTo(this.$el)).done(function () {
- widget.$header && widget.$header.show();
+ (action.target !== 'inline') && (!action.flags.headless) && widget.$header && widget.$header.show();
old_widget && old_widget.$el.hide();
if (clear_breadcrumbs) {
self.clear_view_managers(to_destroy)
@@ -76,33 +83,32 @@ instance.web.ActionManager = instance.web.Widget.extend({
}), true);
},
history_back: function() {
- // var last = this.breadcrumbs.slice(-1)[0];
- // if (!last) {
- // return false;
- // }
- // var title = last.get_title();
- // if (_.isArray(title) && title.length > 1) {
- // return this.select_breadcrumb(this.breadcrumbs.length - 1, title.length - 2);
- // } else if (this.breadcrumbs.length === 1) {
- // // Only one single titled item in breadcrumb, most of the time you want to trigger back to home
- // return false;
- // } else {
- // var prev = this.breadcrumbs[this.breadcrumbs.length - 2];
- // title = prev.get_title();
- // return this.select_breadcrumb(this.breadcrumbs.length - 2, _.isArray(title) ? title.length - 1 : undefined);
- // }
+ var view_manager = _.last(this.view_managers),
+ nbr_views = view_manager.view_stack.length;
+ if (nbr_views > 1) {
+ this.select_view_manager(view_manager, nbr_views - 2);
+ } else if (this.view_managers.length > 1) {
+ view_manager = this.view_managers[this.view_managers.length -2];
+ nbr_views = view_manager.view_stack.length;
+ this.select_view(view_managers, nbr_views - 2)
+ }
},
select_view_manager: function(view_manager, index) {
var self = this;
+ if (this.webclient.has_uncommitted_changes()) {
+ return false;
+ }
var vm_index = this.view_managers.indexOf(view_manager);
- view_manager.select_view(index).done(function () {
- _.each(self.view_managers.splice(vm_index + 1), function (vm) {
- vm.destroy();
+ if (view_manager.select_view) {
+ view_manager.select_view(index).done(function () {
+ _.each(self.view_managers.splice(vm_index + 1), function (vm) {
+ vm.destroy();
+ });
+ self.inner_widget = _.last(self.view_managers);
+ self.inner_widget.display_breadcrumbs();
+ self.inner_widget.$el.show();
});
- self.inner_widget = _.last(self.view_managers);
- self.inner_widget.display_breadcrumbs();
- self.inner_widget.$el.show();
- });
+ }
},
clear_view_managers: function(vms) {
_.each(vms || this.view_managers, function (vm) {
@@ -127,7 +133,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
// });
},
do_push_state: function(state) {
- if (!this.webclient || !this.webclient.do_push_state) {
+ if (!this.webclient || !this.webclient.do_push_state || this.dialog) {
return;
}
state = state || {};
@@ -168,9 +174,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
}
}
}
- if(!this.dialog) {
- this.webclient.do_push_state(state);
- }
+ this.webclient.do_push_state(state);
},
do_load_state: function(state, warm) {
var self = this,
@@ -386,6 +390,9 @@ instance.web.ActionManager = instance.web.Widget.extend({
$buttons: this.dialog.$buttons,
footer_to_buttons: true,
});
+ if (widget.action.view_mode === 'form') {
+ widget.flags.headless = true;
+ }
}
this.dialog_widget = widget;
this.dialog_widget.setParent(this.dialog);
@@ -398,9 +405,6 @@ instance.web.ActionManager = instance.web.Widget.extend({
}
widget = executor.widget();
this.dialog_stop(executor.action);
- if (options.clear_breadcrumbs) {
- // this.clear_view_managers();
- }
return this.push_view_manager(widget, executor.action, options.clear_breadcrumbs);
},
ir_actions_act_window: function (action, options) {
@@ -412,13 +416,6 @@ instance.web.ActionManager = instance.web.Widget.extend({
},
action: action,
klass: 'oe_act_window',
- // post_process: function (widget) {
- // self.push_breadcrumb({
- // widget: widget,
- // on_reverse_breadcrumb: options.on_reverse_breadcrumb,
- // hide_breadcrumb: options.hide_breadcrumb,
- // });
- // },
}, options);
},
ir_actions_client: function (action, options) {
@@ -440,18 +437,9 @@ instance.web.ActionManager = instance.web.Widget.extend({
widget: function () { return new ClientWidget(self, action); },
action: action,
klass: 'oe_act_client',
- // post_process: function(widget) {
- // self.push_breadcrumb({
- // widget: widget,
- // title: action.name,
- // on_reverse_breadcrumb: options.on_reverse_breadcrumb,
- // hide_breadcrumb: options.hide_breadcrumb,
- // });
- // if (action.tag !== 'reload') {
- // self.do_push_state({});
- // }
- // }
- }, options);
+ }, options).then(function () {
+ if (action.tag !== 'reload') {self.do_push_state({});}
+ });
},
ir_actions_act_window_close: function (action, options) {
if (!this.dialog) {
@@ -544,38 +532,46 @@ instance.web.ViewManager = instance.web.Widget.extend({
_.each(views, function (view) {
var view_type = view[1] || view.view_type,
View = instance.web.views.get_object(view_type, true),
- view_label = View ? View.prototype.display_name : (void 'nope');
- self.view_order.push(view_type);
- self.views[view_type] = {
- 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'),
- };
+ view_label = View ? View.prototype.display_name: (void 'nope'),
+ view = {
+ 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);
+ self.views[view_type] = view;
});
+ this.multiple_views = (self.view_order.length - ('form' in this.views ? 1 : 0)) > 1;
},
/**
* @returns {jQuery.Deferred} initial view loading promise
*/
start: function() {
var self = this;
- var default_view = this.flags.default_view || this.view_order[0],
+ 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,
+ 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 a');
+ this.$switch_buttons = this.$('.oe-view-manager-switch button');
this.$header = this.$('.oe-view-manager-header');
-
- self.$switch_buttons.click(function () {
- self.switch_mode($(this).data('view-type'));
+ 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) {
+ if (!$(event.target).hasClass('active')) {
+ self.switch_mode($(this).data('view-type'));
+ }
});
var views_ids = {};
_.each(this.views, function (view) {
@@ -587,21 +583,29 @@ instance.web.ViewManager = instance.web.Widget.extend({
action : self.action,
action_views_ids : views_ids,
}, self.flags, self.flags[view.type], view.options);
+ if (view.type !== 'form') {
+ 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'));
- var search_view_loaded = this.flags.search_view ? this.setup_search_view() : $.when(),
- main_view_loaded = this.switch_mode(default_view, null, default_options);
+ 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, search_view_loaded);
+ 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') {
this.view_stack = [];
- }
+ }
this.view_stack.push(view);
this.active_view = view;
@@ -613,7 +617,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
if (this.searchview
&& this.flags.auto_search
&& view.controller.searchable !== false) {
- $.when(this.searchview.ready, view.created).done(this.searchview.do_search);
+ $.when(this.search_view_loaded, view.created).done(this.searchview.do_search);
} else {
this.active_search.resolve();
}
@@ -623,6 +627,12 @@ instance.web.ViewManager = instance.web.Widget.extend({
self.active_view = view;
self._display_view(view.type, view_options);
self.trigger('switch_mode', view_type, no_store, view_options);
+ if (self.session.debug) {
+ self.$('.oe_debug_view').html(QWeb.render('ViewManagerDebug', {
+ view: self.active_view.controller,
+ view_manager: self,
+ }));
+ }
});
},
update_header: function () {
@@ -642,8 +652,10 @@ instance.web.ViewManager = instance.web.Widget.extend({
});
self.active_view.options.$buttons && self.active_view.options.$buttons.show();
if (self.searchview) {
- var is_hidden = self.active_view.controller.searchable === false || self.searchview.options.hidden;
+ 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();
});
@@ -667,7 +679,8 @@ instance.web.ViewManager = instance.web.Widget.extend({
create_view: function(view) {
var self = this,
View = this.registry.get_object(view.type),
- options = _.clone(view.options);
+ options = _.clone(view.options),
+ view_loaded = $.Deferred();
if (view.type === "form" && this.action && (this.action.target === 'new' || this.action.target === 'inline')) {
options.initial_mode = 'edit';
@@ -677,25 +690,26 @@ instance.web.ViewManager = instance.web.Widget.extend({
$container.hide();
view.controller = controller;
+ view.$container = $container;
if (view.embedded_view) {
controller.set_embedded_view(view.embedded_view);
}
controller.on('switch_mode', this, this.switch_mode.bind(this));
-
- view.$container = $container;
-
- var view_loaded = $.Deferred();
- view.controller.on('view_loaded', this, function () {
+ controller.on('history_back', this, function () {
+ self.action_manager && self.action_manager.trigger('history_back');
+ });
+ controller.on("change:title", this, function() {
+ self.display_breadcrumbs();
+ });
+ controller.on('view_loaded', this, function () {
view_loaded.resolve();
});
-
return $.when(controller.appendTo($container), view_loaded)
.done(function () {
self.trigger("controller_inited", view.type, controller);
});
},
-
select_view: function (index) {
var view_type = this.view_stack[index].type;
this.view_stack.splice(index);
@@ -713,6 +727,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
}
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 : [];
@@ -727,13 +742,13 @@ instance.web.ViewManager = instance.web.Widget.extend({
var options = {
hidden: this.flags.search_view === false,
disable_custom_filters: this.flags.search_disable_custom_filters,
+ $buttons: this.$('.oe-search-options'),
};
var SearchView = instance.web.SearchView;
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"),
- this.$('.oe_searchview_drawer_container'));
+ return this.searchview.appendTo(this.$(".oe-view-manager-search-view:first"));
},
search: function(domains, contexts, groupbys) {
var self = this,
@@ -783,6 +798,145 @@ instance.web.ViewManager = instance.web.Widget.extend({
self.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 instance.web.Dialog(this, { title: _t("Fields View Get") }).open();
+ $('<pre>').text(instance.web.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 instance.web.Dialog(this, {
+ title: _.str.sprintf(_t("Metadata (%s)"), self.dataset.model),
+ size: 'medium',
+ }, QWeb.render('ViewManagerDebugViewLog', {
+ perm : result[0],
+ format : instance.web.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 instance.web.Dialog(self, {
+ title: _.str.sprintf(_t("Model %s fields"),
+ self.dataset.model),
+ }, $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) {
+ instance.web.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: instance.web.unblockUI
+ });
+ }
+ 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,
+ }
+ });
+ },
});
instance.web.ViewManagerAction = instance.web.ViewManager.extend({
@@ -793,9 +947,25 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
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;
var dataset = new instance.web.DataSetSearch(this, action.res_model, action.context, action.domain);
+ if (action.res_id) {
+ dataset.ids.push(action.res_id);
+ dataset.index = 0;
+ }
this._super(parent, dataset, action.views, flags);
}
});
@@ -824,7 +994,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
var self = this;
this._super(this);
this.redraw();
- this.$el.on('click','.oe_dropdown_menu li a', function(event) {
+ this.$el.on('click','.dropdown-menu li a', function(event) {
var section = $(this).data('section');
var index = $(this).data('index');
var item = self.items[section][index];