diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index 92987ffa639..96782c1cec4 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -9,6 +9,8 @@ import openerpweb import openerpweb.ast import openerpweb.nonliterals +import cherrypy + # Should move to openerpweb.Xml2Json class Xml2Json: # xml2json-direct @@ -168,26 +170,71 @@ class Session(openerpweb.Controller): 'domain': domain, 'group_by': group_by_sequence } + + @openerpweb.jsonrequest + def save_session_action(self, req, the_action): + """ + This method store an action object in the session object and returns an integer + identifying that action. The method get_session_action() can be used to get + back the action. + + :param the_action: The action to save in the session. + :type the_action: anything + :return: A key identifying the saved action. + :rtype: integer + """ + saved_actions = cherrypy.session.get('saved_actions') + if not saved_actions: + saved_actions = {"next":0, "actions":{}} + cherrypy.session['saved_actions'] = saved_actions + # we don't allow more than 10 stored actions + if len(saved_actions["actions"]) >= 10: + del saved_actions["actions"][min(saved_actions["actions"].keys())] + key = saved_actions["next"] + saved_actions["actions"][key] = the_action + saved_actions["next"] = key + 1 + return key + + @openerpweb.jsonrequest + def get_session_action(self, req, key): + """ + Gets back a previously saved action. This method can return None if the action + was saved since too much time (this case should be handled in a smart way). + + :param key: The key given by save_session_action() + :type key: integer + :return: The saved action or None. + :rtype: anything + """ + saved_actions = cherrypy.session.get('saved_actions') + if not saved_actions: + return None + return saved_actions["actions"].get(key) + 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 {} + clean_action(action, req.session) - if isinstance(action['domain'], basestring): - action['domain'] = eval( - action['domain'], - req.session.evaluation_context( - action['context'])) or [] - fix_view_modes(action) return actions +def clean_action(action, session): + # values come from the server, we can just eval them + if isinstance(action['context'], basestring): + action['context'] = eval( + action['context'], + session.evaluation_context()) or {} + + if isinstance(action['domain'], basestring): + action['domain'] = eval( + action['domain'], + session.evaluation_context( + action['context'])) or [] + fix_view_modes(action) + 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): @@ -354,9 +401,9 @@ class DataSet(openerpweb.Controller): return {'result': r} class View(openerpweb.Controller): - def fields_view_get(self, session, model, view_id, view_type, transform=True): + def fields_view_get(self, session, model, view_id, view_type, transform=True, toolbar=False, submenu=False): Model = session.model(model) - r = Model.fields_view_get(view_id, view_type) + r = Model.fields_view_get(view_id, view_type, {}, toolbar, submenu) if transform: context = {} # TODO: dict(ctx_sesssion, **ctx_action) xml = self.transform_view(r['arch'], session, context) @@ -460,16 +507,16 @@ class FormView(View): _cp_path = "/base/formview" @openerpweb.jsonrequest - def load(self, req, model, view_id): - fields_view = self.fields_view_get(req.session, model, view_id, 'form') + def load(self, req, model, view_id, toolbar=False): + fields_view = self.fields_view_get(req.session, model, view_id, 'form', toolbar=toolbar) return {'fields_view': fields_view} class ListView(View): _cp_path = "/base/listview" @openerpweb.jsonrequest - def load(self, req, model, view_id): - fields_view = self.fields_view_get(req.session, model, view_id, 'tree') + def load(self, req, model, view_id, toolbar=False): + fields_view = self.fields_view_get(req.session, model, view_id, 'tree', toolbar=toolbar) return {'fields_view': fields_view} class SearchView(View): @@ -479,15 +526,6 @@ 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): _cp_path = "/base/action" diff --git a/addons/base/static/src/base.html b/addons/base/static/src/base.html index f8c700946f3..3c8f76a6e23 100644 --- a/addons/base/static/src/base.html +++ b/addons/base/static/src/base.html @@ -3,7 +3,7 @@ OpenERP - + diff --git a/addons/base/static/src/js/data.js b/addons/base/static/src/js/data.js index 1e96dde23fc..8f5d6168e75 100644 --- a/addons/base/static/src/js/data.js +++ b/addons/base/static/src/js/data.js @@ -99,7 +99,7 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base. context: this.context }, callback); }, - unlink: function() { + unlink: function(ids) { this.notification['default']("Unlink", ids); }, call: function (method, ids, args, callback) { @@ -111,7 +111,7 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base. ids: ids, args: args }, callback); - }, + } }); openerp.base.DataSetStatic = openerp.base.DataSet.extend({ @@ -123,7 +123,7 @@ openerp.base.DataSetStatic = openerp.base.DataSet.extend({ }, read_slice: function (fields, offset, limit, callback) { this.read_ids(this.ids.slice(offset, offset + limit)); - }, + } }); openerp.base.DataSetSearch = openerp.base.DataSet.extend({ @@ -163,7 +163,7 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({ } callback(records); }); - }, + } }); openerp.base.DataSetRelational = openerp.base.DataSet.extend( /** @lends openerp.base.DataSet# */{ diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index ff04f55314b..bf42fc4fd7f 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -30,7 +30,8 @@ openerp.base.FormView = openerp.base.Controller.extend( /** @lends openerp.base }, start: function() { //this.log('Starting FormView '+this.model+this.view_id) - return this.rpc("/base/formview/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded); + return this.rpc("/base/formview/load", {"model": this.model, "view_id": this.view_id, + toolbar:!!this.view_manager.sidebar}, this.on_loaded); }, on_loaded: function(data) { var self = this; @@ -54,7 +55,7 @@ openerp.base.FormView = openerp.base.Controller.extend( /** @lends openerp.base // sidebar stuff if (this.view_manager.sidebar) { - this.view_manager.sidebar.load_multi_actions(); + this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar); } }, do_show: function () { @@ -140,7 +141,7 @@ openerp.base.FormView = openerp.base.Controller.extend( /** @lends openerp.base var ajax = { url: '/base/dataset/call', async: false - } + }; return this.rpc(ajax, { model: this.dataset.model, method: method, @@ -212,7 +213,7 @@ openerp.base.FormView = openerp.base.Controller.extend( /** @lends openerp.base if (invalid) { this.on_invalid(); } else { - this.log("About to save", values) + this.log("About to save", values); this.dataset.write(this.datarecord.id, values, this.on_saved); } }, @@ -244,8 +245,13 @@ openerp.base.FormView = openerp.base.Controller.extend( /** @lends openerp.base } }, do_search: function (domains, contexts, groupbys) { + this.notification['default']("Searching form"); }, on_action: function (action) { + this.notification['default']('Executing action ' + action); + }, + do_cancel: function () { + this.notification['default']("Cancelling form"); } }); @@ -698,7 +704,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ }, set_value: function(value) { this._super.apply(this, arguments); - var show_value = '' + var show_value = ''; if (value != null && value !== false) { show_value = value[1]; this.value = value[0]; @@ -713,17 +719,15 @@ openerp.base.form.FieldOne2ManyDatasSet = openerp.base.DataSetStatic.extend({ write: function (id, data, callback) { this._super(id, data, callback); }, - write: function (id, data, callback) { - this._super(id, data, callback); - }, unlink: function() { + this.notification['default']('Unlinking o2m ' + this.ids); } }); openerp.base.form.FieldOne2ManyViewManager = openerp.base.ViewManager.extend({ init: function(session, element_id, dataset, views) { this._super(session, element_id, dataset, views); - }, + } }); openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 533ff0d9deb..4b1eeaaf993 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -36,7 +36,8 @@ openerp.base.ListView = openerp.base.Controller.extend( }, start: function() { //this.log('Starting ListView '+this.model+this.view_id) - return this.rpc("/base/listview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded); + return this.rpc("/base/listview/load", {"model": this.model, "view_id":this.view_id, + toolbar:!!this.view_manager.sidebar}, this.on_loaded); }, on_loaded: function(data) { this.fields_view = data.fields_view; @@ -73,8 +74,9 @@ openerp.base.ListView = openerp.base.Controller.extend( 'tr', 'click', this.on_select_row); // sidebar stuff - if (this.view_manager.sidebar) - this.view_manager.sidebar.load_multi_actions(); + if (this.view_manager.sidebar) { + this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar); + } }, /** * Fills the table with the provided records after emptying it @@ -83,7 +85,6 @@ openerp.base.ListView = openerp.base.Controller.extend( * @returns {Promise} promise to the end of view rendering (list views are asynchronously filled for improved responsiveness) */ do_fill_table: function(records) { - console.log("listview do_fill",records) this.rows = records; var $table = this.$element.find('table'); @@ -148,7 +149,6 @@ openerp.base.ListView = openerp.base.Controller.extend( }, do_search: function (domains, contexts, groupbys) { var self = this; - console.log("listview do_search",domains) this.rpc('/base/session/eval_domain_and_context', { domains: domains, contexts: contexts, diff --git a/addons/base/static/src/js/views.js b/addons/base/static/src/js/views.js index 6adc0fc3d38..747a35dedbc 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.ViewManagerAction(this.session,this.element_id, action, false); + this.viewmanager = new openerp.base.ViewManagerAction(this.session,this.element_id, action, true); this.viewmanager.start(); } } @@ -141,7 +141,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({ this.sidebar = new openerp.base.Sidebar(null, this); }, start: function() { - var self = this; var inital_view_loaded = this._super(); // init sidebar @@ -159,10 +158,13 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({ search_defaults[match[1]] = value; } }); - var searchview_loaded = this.setup_search_view(view_id,search_defaults); + var searchview_loaded = null; + if (view_id) { + searchview_loaded = this.setup_search_view(view_id,search_defaults); + } // schedule auto_search - if (this.action['auto_search']) { + if (searchview_loaded != null && this.action['auto_search']) { $.when(searchview_loaded, inital_view_loaded) .then(this.searchview.do_search); } @@ -173,29 +175,30 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({ this.sidebar.stop(); } this._super(); - }, + } }); openerp.base.BaseWidget = openerp.base.Controller.extend({ /** - * The name of the QWeb template that will be used for rendering. Must be redifined - * in subclasses or the render() method can not be used. + * The name of the QWeb template that will be used for rendering. Must be + * redefined in subclasses or the render() method can not be used. * * @type string */ template: null, /** - * The prefix used to generate an id automatically. Should be redifined in subclasses. - * If it is not defined, a default identifier will be used. + * The prefix used to generate an id automatically. Should be redefined in + * subclasses. If it is not defined, a default identifier will be used. * * @type string */ identifier_prefix: 'generic-identifier', /** - * Base class for widgets. Handle rendering (based on a QWeb template), identifier - * generation, parenting and destruction of the widget. - * Contructor. Also initialize the identifier. - * + * Base class for widgets. Handle rendering (based on a QWeb template), + * identifier generation, parenting and destruction of the widget. + * Also initialize the identifier. + * + * @constructs * @params {openerp.base.search.BaseWidget} parent The parent widget. */ init: function (parent, session) { @@ -242,8 +245,8 @@ openerp.base.BaseWidget = openerp.base.Controller.extend({ this._super(); }, /** - * Set the parent of this component, also unregister the previous parent if there - * was one. + * Set the parent of this component, also un-register the previous parent + * if there was one. * * @param {openerp.base.BaseWidget} parent The new parent. */ @@ -274,27 +277,26 @@ openerp.base.Sidebar = openerp.base.BaseWidget.extend({ this.view_manager = view_manager; this.sections = []; }, - load_multi_actions: function() { - if (_.detect(this.sections, function(x) {return x.type=="multi_actions";}) != undefined) - return; + set_toolbar: function(toolbar) { + this.sections = []; 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(); + _.each(["print", "action", "relate"], function(type) { + if (toolbar[type].length == 0) + return; + var section = {elements:toolbar[type]}; + self.sections.push(section); }); + this.refresh(); }, refresh: function() { this.$element.html(QWeb.render("ViewManager.sidebar.internal", _.extend({_:_}, this))); var self = this; this.$element.find("a").click(function(e) { - $this = jQuery(this); + var $this = jQuery(this); var i = $this.attr("data-i"); - var j = $this.attr("data-i"); + var j = $this.attr("data-j"); 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); + (new openerp.base.ExternalActionManager(self.view_manager.session, null)) .handle_action(action); e.stopPropagation(); e.preventDefault(); }); @@ -305,6 +307,30 @@ openerp.base.Sidebar = openerp.base.BaseWidget.extend({ } }); +openerp.base.ExternalActionManager = openerp.base.Controller.extend({ + handle_action: function(action) { + if(action.type=="ir.actions.act_window") { + if(action.target=="new") { + var element_id = _.uniqueId("act_window_dialog"); + var dialog = $('
'); + dialog.dialog({ + title: action.name + }); + var viewmanager = new openerp.base.ViewManagerAction(this.session ,element_id, action, false); + viewmanager.start(); + } else if (action.target == "current") { + this.rpc("/base/session/save_session_action", {the_action:action}, function(key) { + var url = window.location.href; + //window.open(); + }); + } + } + // TODO: show an error like "not implemented" here + // since we don't currently have any way to handle errors do you have any better idea + // than using todos? + } +}); + openerp.base.views.add('calendar', 'openerp.base.CalendarView'); openerp.base.CalendarView = openerp.base.Controller.extend({ start: function () { diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml index f93a38c96fc..caf463cf4e0 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -533,8 +533,8 @@ diff --git a/openerpweb/openerpweb.py b/openerpweb/openerpweb.py index 69ae2f43108..6a4d4146280 100644 --- a/openerpweb/openerpweb.py +++ b/openerpweb/openerpweb.py @@ -18,6 +18,7 @@ import simplejson import nonliterals import xmlrpctimeout +import logging #----------------------------------------------------------- # Globals @@ -355,6 +356,8 @@ class JsonRequest(object): } } except Exception: + cherrypy.log("An error occured while handling a json request", + severity=logging.ERROR, traceback=True) error = { 'code': 300, 'message': "OpenERP WebClient Error", @@ -495,3 +498,4 @@ def main(argv): cherrypy.server.subscribe() cherrypy.engine.start() cherrypy.engine.block() +