diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index e1df0a4d8b7..ba24c055f70 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -171,6 +171,54 @@ class Session(openerpweb.Controller): 'domain': domain, 'group_by': group_by_sequence } + +def load_actions_from_ir_values(req, key, key2, models, meta, context): + Values = req.session.model('ir.values') + actions = Values.get(key, key2, models, meta, context) + + for _, _, action in actions: + # values come from the server, we can just eval them + if isinstance(action['context'], basestring): + action['context'] = eval( + action['context'], + req.session.evaluation_context()) or {} + + if isinstance(action['domain'], basestring): + action['domain'] = eval( + action['domain'], + req.session.evaluation_context( + action['context'])) or [] + fix_view_modes(action) + return actions + +def fix_view_modes(action): + """ For historical reasons, OpenERP has weird dealings in relation to + view_mode and the view_type attribute (on window actions): + + * one of the view modes is ``tree``, which stands for both list views + and tree views + * the choice is made by checking ``view_type``, which is either + ``form`` for a list view or ``tree`` for an actual tree view + + This methods simply folds the view_type into view_mode by adding a + new view mode ``list`` which is the result of the ``tree`` view_mode + in conjunction with the ``form`` view_type. + + TODO: this should go into the doc, some kind of "peculiarities" section + + :param dict action: an action descriptor + :returns: nothing, the action is modified in place + """ + if action.pop('view_type') != 'form': + return + + action['view_mode'] = ','.join( + mode if mode != 'tree' else 'list' + for mode in action['view_mode'].split(',')) + action['views'] = [ + [id, mode if mode != 'tree' else 'list'] + for id, mode in action['views'] + ] class Menu(openerpweb.Controller): _cp_path = "/base/menu" @@ -215,55 +263,11 @@ class Menu(openerpweb.Controller): @openerpweb.jsonrequest def action(self, req, menu_id): - Values = req.session.model('ir.values') - actions = Values.get('action', 'tree_but_open', [('ir.ui.menu', menu_id)], False, {}) - - for _, _, action in actions: - # values come from the server, we can just eval them - if isinstance(action['context'], basestring): - action['context'] = eval( - action['context'], - req.session.evaluation_context()) or {} - - if isinstance(action['domain'], basestring): - action['domain'] = eval( - action['domain'], - req.session.evaluation_context( - action['context'])) or [] - - self.fix_view_modes(action) + actions = load_actions_from_ir_values(req,'action', 'tree_but_open', + [('ir.ui.menu', menu_id)], False, {}) return {"action": actions} - def fix_view_modes(self, action): - """ For historical reasons, OpenERP has weird dealings in relation to - view_mode and the view_type attribute (on window actions): - - * one of the view modes is ``tree``, which stands for both list views - and tree views - * the choice is made by checking ``view_type``, which is either - ``form`` for a list view or ``tree`` for an actual tree view - - This methods simply folds the view_type into view_mode by adding a - new view mode ``list`` which is the result of the ``tree`` view_mode - in conjunction with the ``form`` view_type. - - TODO: this should go into the doc, some kind of "peculiarities" section - - :param dict action: an action descriptor - :returns: nothing, the action is modified in place - """ - if action.pop('view_type') != 'form': - return - - action['view_mode'] = ','.join( - mode if mode != 'tree' else 'list' - for mode in action['view_mode'].split(',')) - action['views'] = [ - [id, mode if mode != 'tree' else 'list'] - for id, mode in action['views'] - ] - class DataSet(openerpweb.Controller): _cp_path = "/base/dataset" @@ -469,6 +473,15 @@ class SearchView(View): def load(self, req, model, view_id): fields_view = self.fields_view_get(req.session, model, view_id, 'search') return {'fields_view': fields_view} + +class SideBar(View): + _cp_path = "/base/sidebar" + + @openerpweb.jsonrequest + def get_actions(self, request, model, object_id=0): + result = load_actions_from_ir_values(request, "action", "client_action_multi", + [[model, object_id]], False, {}) + return result class Action(openerpweb.Controller): diff --git a/addons/base/static/src/css/base.css b/addons/base/static/src/css/base.css index 343c6688081..b15585ac062 100644 --- a/addons/base/static/src/css/base.css +++ b/addons/base/static/src/css/base.css @@ -449,3 +449,25 @@ body.openerp { font-size: 1em; } +/* Sidebar */ +.openerp .view-manager-main-sidebar { + vertical-align: top; +} + +.openerp .view-manager-main-sidebar .sidebar-main-div { + border: solid 1px #1F1F1F; + border-bottom-width: 0; +} + +.openerp .view-manager-main-sidebar ul { + list-style-type: none; + margin: 0; + padding: 0; + width: 120px; + border-bottom: solid 1px #1F1F1F; +} + +.openerp .view-manager-main-sidebar li { + padding: 3px; +} + diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index b84b3a146ab..e13178afbf5 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -15,8 +15,9 @@ openerp.base.FormView = openerp.base.Controller.extend( /** @lends openerp.base * @param {openerp.base.DataSet} dataset the dataset this view will work with * @param {String} view_id the identifier of the OpenERP view object */ - init: function(session, element_id, dataset, view_id) { + init: function(view_manager, session, element_id, dataset, view_id) { this._super(session, element_id); + this.view_manager = view_manager; this.dataset = dataset; this.model = dataset.model; this.view_id = view_id; @@ -45,6 +46,10 @@ openerp.base.FormView = openerp.base.Controller.extend( /** @lends openerp.base var action = $(this).data('pager-action'); self.on_pager_action(action); }); + + // sidebar stuff + if (this.view_manager.sidebar) + this.view_manager.sidebar.load_multi_actions(); }, on_record_loaded: function(record) { if (record.length) { diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index f3565635c79..1eb3d5d50e1 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -3,8 +3,9 @@ openerp.base.list = function (openerp) { openerp.base.views.add('list', 'openerp.base.ListView'); openerp.base.ListView = openerp.base.Controller.extend({ - init: function(session, element_id, dataset, view_id) { + init: function(view_manager, session, element_id, dataset, view_id) { this._super(session, element_id); + this.view_manager = view_manager; this.dataset = dataset; this.model = dataset.model; this.view_id = view_id; @@ -65,6 +66,10 @@ openerp.base.ListView = openerp.base.Controller.extend({ self.$table.setGridWidth(self.$element.width()); self.$element.children().show(); }).trigger('resize'); + + // sidebar stuff + if (this.view_manager.sidebar) + this.view_manager.sidebar.load_multi_actions(); }, do_fill_table: function(records) { this.log("do_fill_table"); diff --git a/addons/base/static/src/js/search.js b/addons/base/static/src/js/search.js index be8ca5cff3d..3d3bb016a82 100644 --- a/addons/base/static/src/js/search.js +++ b/addons/base/static/src/js/search.js @@ -1,8 +1,9 @@ openerp.base.search = function(openerp) { openerp.base.SearchView = openerp.base.Controller.extend({ - init: function(session, element_id, dataset, view_id, defaults) { + init: function(view_manager, session, element_id, dataset, view_id, defaults) { this._super(session, element_id); + this.view_manager = view_manager; this.dataset = dataset; this.model = dataset.model; this.view_id = view_id; @@ -388,7 +389,7 @@ openerp.base.search.ExtendedSearch = openerp.base.BaseWidget.extend({ var _this = this; openerp.base.search.add_expand_listener(this.$element); this.add_group(); - this.$element.find('.searchview_extended_add_group').click(function () { + this.$element.find('.searchview_extended_add_group').click(function (e) { _this.add_group(); }); }, @@ -421,7 +422,7 @@ openerp.base.search.ExtendedSearchGroup = openerp.base.BaseWidget.extend({ this._super(); var _this = this; this.add_prop(); - this.$element.find('.searchview_extended_add_proposition').click(function () { + this.$element.find('.searchview_extended_add_proposition').click(function (e) { _this.add_prop(); }); var delete_btn = this.$element.find('.searchview_extended_delete_group'); @@ -474,7 +475,7 @@ openerp.base.search.Filter = openerp.base.search.Input.extend({ start: function () { this._super(); var self = this; - this.$element.click(function () { + this.$element.click(function (e) { $(this).toggleClass('enabled'); self.view.do_toggle_filter(self); }); @@ -772,7 +773,7 @@ openerp.base.search.ExtendedSearchProposition = openerp.base.BaseWidget.extend({ _this.changed(); }); var delete_btn = this.$element.find('.searchview_extended_delete_prop'); - delete_btn.click(function () { + delete_btn.click(function (e) { _this.stop(); }); }, diff --git a/addons/base/static/src/js/views.js b/addons/base/static/src/js/views.js index d6d2e5b6064..fb6f78f7d9e 100644 --- a/addons/base/static/src/js/views.js +++ b/addons/base/static/src/js/views.js @@ -20,7 +20,7 @@ openerp.base.ActionManager = openerp.base.Controller.extend({ if (this.viewmanager) { this.viewmanager.stop(); } - this.viewmanager = new openerp.base.ViewManager(this.session,this.element_id); + this.viewmanager = new openerp.base.ViewManager(this.session,this.element_id, false); this.viewmanager.do_action_window(action); this.viewmanager.start(); } @@ -33,15 +33,30 @@ openerp.base.ActionManager = openerp.base.Controller.extend({ openerp.base.views = new openerp.base.Registry(); openerp.base.ViewManager = openerp.base.Controller.extend({ - init: function(session, element_id) { + init: function(session, element_id, desactivate_sidebar) { this._super(session, element_id); this.action = null; this.dataset = null; this.searchview = null; this.active_view = null; this.views = {}; + if (desactivate_sidebar) + this.sidebar = null; + else + this.sidebar = new openerp.base.Sidebar(null, this); }, start: function() { + if (this.sidebar) { + this.$element.find('.view-manager-main-sidebar').html(this.sidebar.render()); + this.sidebar.start(); + } + }, + stop: function() { + // should be replaced by automatic destruction implemented in BaseWidget + if (this.sidebar) { + this.sidebar.stop(); + } + this._super(); }, do_action_window: function(action) { var self = this; @@ -89,7 +104,7 @@ openerp.base.ViewManager = openerp.base.Controller.extend({ if (!view.controller) { // Lazy loading of views var controller = new (openerp.base.views.get_object(view_type))( - this.session, this.element_id + "_view_" + view_type, this.dataset, view.view_id); + this, this.session, this.element_id + "_view_" + view_type, this.dataset, view.view_id); view_promise = controller.start(); this.views[view_type].controller = controller; } @@ -148,7 +163,7 @@ openerp.base.ViewManager = openerp.base.Controller.extend({ } var view_id = action.search_view_id ? action.search_view_id[0] || false : false; - this.searchview = new openerp.base.SearchView(this.session, this.element_id + "_search", this.dataset, view_id, this.search_defaults()); + this.searchview = new openerp.base.SearchView(this, this.session, this.element_id + "_search", this.dataset, view_id, this.search_defaults()); this.searchview.on_search.add(function() { self.views[self.active_view].controller.do_search.apply(self, arguments); }); @@ -191,13 +206,14 @@ openerp.base.BaseWidget = openerp.base.Controller.extend({ */ identifier_prefix: 'generic-identifier', /** - * Base class for widgets. Handle rendering (based on a QWeb template), identifier - * generation, parenting and destruction of the widget. + * Base class for widgets. Handle rendering (based on a QWeb template), identifier + * generation, parenting and destruction of the widget. * Contructor. Also initialize the identifier. * * @params {openerp.base.search.BaseWidget} parent The parent widget. */ - init: function (parent) { + init: function (parent, session) { + this._super(session); this.children = []; this.parent = null; this.set_parent(parent); @@ -265,7 +281,46 @@ openerp.base.BaseWidget = openerp.base.Controller.extend({ } }); +openerp.base.Sidebar = openerp.base.BaseWidget.extend({ + template: "ViewManager.sidebar", + init: function(parent, view_manager) { + this._super(parent, view_manager.session); + this.view_manager = view_manager; + this.sections = []; + }, + load_multi_actions: function() { + if (_.detect(this.sections, function(x) {return x.type=="multi_actions";}) != undefined) + return; + var self = this; + this.rpc("/base/sidebar/get_actions", + {"model": this.view_manager.dataset.model}, function(result) { + self.sections.push({type: "multi_actions", elements: + _.map(result, function(x) {return {text:x[2].name, action:x}; })}); + self.refresh(); + }); + }, + refresh: function() { + this.$element.html(QWeb.render("ViewManager.sidebar.internal", this)); + var self = this; + this.$element.find("a").click(function(e) { + $this = jQuery(this); + var i = $this.attr("data-i"); + var j = $this.attr("data-i"); + var action = self.sections[i].elements[j]; + // I know this doesn't work, one day it will + new openerp.base.ActionManager(this.view_manager, null).do_action(action); + e.stopPropagation(); + e.preventDefault(); + }); + }, + start: function() { + this._super(); + this.refresh(); + } +}); + openerp.base.views.add('calendar', 'openerp.base.CalendarView'); + openerp.base.CalendarView = openerp.base.Controller.extend({ start: function () { this._super(); diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml index d8ef6cf93ad..b8efa70d894 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -118,6 +118,9 @@ + + + + + +
@@ -130,6 +133,11 @@
+
+