diff --git a/addons/base/__init__.py b/addons/base/__init__.py index ee5959455ad..343b53d050d 100644 --- a/addons/base/__init__.py +++ b/addons/base/__init__.py @@ -1 +1,6 @@ +import common import controllers + +# TODO +# if we detect that we are imported from the openerp server register common.Root() as a wsgi entry point + diff --git a/addons/base/common/__init__.py b/addons/base/common/__init__.py new file mode 100644 index 00000000000..60699c86f43 --- /dev/null +++ b/addons/base/common/__init__.py @@ -0,0 +1,5 @@ +#!/usr/bin/python +# TODO if from openerpserver use backendlocal +# from backendlocal import * +from backendrpc import * +from dispatch import * diff --git a/openerpweb/ast.py b/addons/base/common/ast.py similarity index 100% rename from openerpweb/ast.py rename to addons/base/common/ast.py diff --git a/addons/base/common/backendlocal.py b/addons/base/common/backendlocal.py new file mode 100644 index 00000000000..dac33991c4d --- /dev/null +++ b/addons/base/common/backendlocal.py @@ -0,0 +1,23 @@ +#---------------------------------------------------------- +# OpenERPSession local openerp backend access +#---------------------------------------------------------- +class OpenERPUnboundException(Exception): + pass + +class OpenERPConnector(object): + pass + +class OpenERPAuth(object): + pass + +class OpenERPModel(object): + def __init__(self, session, model): + self._session = session + self._model = model + + def __getattr__(self, name): + return lambda *l:self._session.execute(self._model, name, *l) + +class OpenERPSession(object): + def __init__(self, model_factory=OpenERPModel): + pass diff --git a/addons/base/common/backendrpc.py b/addons/base/common/backendrpc.py new file mode 100644 index 00000000000..d2e2f6615e1 --- /dev/null +++ b/addons/base/common/backendrpc.py @@ -0,0 +1,212 @@ +#!/usr/bin/python +import datetime +import urllib +import dateutil.relativedelta +import functools +import logging +import optparse +import os +import sys +import tempfile +import time +import traceback +import uuid +import xmlrpclib + +import cherrypy +import cherrypy.lib.static +import simplejson + +import nonliterals +#---------------------------------------------------------- +# OpenERPSession RPC openerp backend access +#---------------------------------------------------------- +class OpenERPUnboundException(Exception): + pass + +class OpenERPConnector(object): + pass + +class OpenERPAuth(object): + pass + +class OpenERPModel(object): + def __init__(self, session, model): + self._session = session + self._model = model + + def __getattr__(self, name): + return lambda *l:self._session.execute(self._model, name, *l) + +class OpenERPSession(object): + """ + An OpenERP RPC session, a given user can own multiple such sessions + in a web session. + + .. attribute:: context + + The session context, a ``dict``. Can be reloaded by calling + :meth:`openerpweb.openerpweb.OpenERPSession.get_context` + + .. attribute:: domains_store + + A ``dict`` matching domain keys to evaluable (but non-literal) domains. + + Used to store references to non-literal domains which need to be + round-tripped to the client browser. + """ + def __init__(self, server='127.0.0.1', port=8069, model_factory=OpenERPModel): + self._server = server + self._port = port + self._db = False + self._uid = False + self._login = False + self._password = False + self.model_factory = model_factory + self._locale = 'en_US' + self.context = {} + self.contexts_store = {} + self.domains_store = {} + self._lang = {} + self.remote_timezone = 'utc' + self.client_timezone = False + + def proxy(self, service): + s = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/%s' % (self._server, self._port, service)) + return s + + def bind(self, db, uid, password): + self._db = db + self._uid = uid + self._password = password + + def login(self, db, login, password): + uid = self.proxy('common').login(db, login, password) + self.bind(db, uid, password) + self._login = login + + if uid: self.get_context() + return uid + + def assert_valid(self): + """ + Ensures this session is valid (logged into the openerp server) + """ + if not (self._db and self._uid and self._password): + raise OpenERPUnboundException() + + def execute(self, model, func, *l, **d): + self.assert_valid() + r = self.proxy('object').execute(self._db, self._uid, self._password, model, func, *l, **d) + return r + + def exec_workflow(self, model, id, signal): + self.assert_valid() + r = self.proxy('object').exec_workflow(self._db, self._uid, self._password, model, signal, id) + return r + + def model(self, model): + """ Get an RPC proxy for the object ``model``, bound to this session. + + :param model: an OpenERP model name + :type model: str + :rtype: :class:`openerpweb.openerpweb.OpenERPModel` + """ + return self.model_factory(self, model) + + def get_context(self): + """ Re-initializes the current user's session context (based on + his preferences) by calling res.users.get_context() with the old + context + + :returns: the new context + """ + assert self._uid, "The user needs to be logged-in to initialize his context" + self.context = self.model('res.users').context_get(self.context) + self.context = self.context or {} + + self.client_timezone = self.context.get("tz", False) + # invalid code, anyway we decided the server will be in UTC + #if self.client_timezone: + # self.remote_timezone = self.execute('common', 'timezone_get') + + self._locale = self.context.get('lang','en_US') + lang_ids = self.execute('res.lang','search', [('code', '=', self._locale)]) + if lang_ids: + self._lang = self.execute('res.lang', 'read',lang_ids[0], []) + return self.context + + @property + def base_eval_context(self): + """ Default evaluation context for the session. + + Used to evaluate contexts and domains. + """ + base = dict( + uid=self._uid, + current_date=datetime.date.today().strftime('%Y-%m-%d'), + time=time, + datetime=datetime, + relativedelta=dateutil.relativedelta.relativedelta + ) + base.update(self.context) + return base + + def evaluation_context(self, context=None): + """ Returns the session's evaluation context, augmented with the + provided context if any. + + :param dict context: to add merge in the session's base eval context + :returns: the augmented context + :rtype: dict + """ + d = dict(self.base_eval_context) + if context: + d.update(context) + d['context'] = d + return d + + def eval_context(self, context_to_eval, context=None): + """ Evaluates the provided context_to_eval in the context (haha) of + the context. Also merges the evaluated context with the session's context. + + :param context_to_eval: a context to evaluate. Must be a dict or a + non-literal context. If it's a dict, will be + returned as-is + :type context_to_eval: openerpweb.nonliterals.Context + :returns: the evaluated context + :rtype: dict + + :raises: ``TypeError`` if ``context_to_eval`` is neither a dict nor + a Context + """ + ctx = dict( + self.base_eval_context, + **(context or {})) + + # adding the context of the session to send to the openerp server + ccontext = nonliterals.CompoundContext(self.context, context_to_eval or {}) + ccontext.session = self + return ccontext.evaluate(ctx) + + def eval_domain(self, domain, context=None): + """ Evaluates the provided domain using the provided context + (merged with the session's evaluation context) + + :param domain: an OpenERP domain as a list or as a + :class:`openerpweb.nonliterals.Domain` instance + + In the second case, it will be evaluated and returned. + :type domain: openerpweb.nonliterals.Domain + :param dict context: the context to use in the evaluation, if any. + :returns: the evaluated domain + :rtype: list + + :raises: ``TypeError`` if ``domain`` is neither a list nor a Domain + """ + if isinstance(domain, list): + return domain + + cdomain = nonliterals.CompoundDomain(domain) + cdomain.session = self + return cdomain.evaluate(context or {}) diff --git a/openerpweb/dates.py b/addons/base/common/dates.py similarity index 100% rename from openerpweb/dates.py rename to addons/base/common/dates.py diff --git a/openerpweb/openerpweb.py b/addons/base/common/dispatch.py similarity index 61% rename from openerpweb/openerpweb.py rename to addons/base/common/dispatch.py index b2364692203..7d50785bf56 100644 --- a/openerpweb/openerpweb.py +++ b/addons/base/common/dispatch.py @@ -3,6 +3,7 @@ import datetime import urllib import dateutil.relativedelta import functools +import logging import optparse import os import sys @@ -17,14 +18,18 @@ import cherrypy.lib.static import simplejson import nonliterals -import logging +# TODO if from openerpserver use backendlocal +# from backendlocal import * +from backendrpc import * #----------------------------------------------------------- # Globals #----------------------------------------------------------- -path_root = os.path.dirname(os.path.dirname(os.path.normpath(__file__))) -path_addons = os.path.join(path_root, 'addons') +import __main__ + +path_root = __main__.path_root +path_addons = __main__.path_addons cherrypy_root = None #----------------------------------------------------------- @@ -38,199 +43,6 @@ controllers_class = {} controllers_object = {} controllers_path = {} -#---------------------------------------------------------- -# OpenERP Client Library -#---------------------------------------------------------- -class OpenERPUnboundException(Exception): - pass - -class OpenERPConnector(object): - pass - -class OpenERPAuth(object): - pass - -class OpenERPModel(object): - def __init__(self, session, model): - self._session = session - self._model = model - - def __getattr__(self, name): - return lambda *l:self._session.execute(self._model, name, *l) - -class OpenERPSession(object): - """ - An OpenERP RPC session, a given user can own multiple such sessions - in a web session. - - .. attribute:: context - - The session context, a ``dict``. Can be reloaded by calling - :meth:`openerpweb.openerpweb.OpenERPSession.get_context` - - .. attribute:: domains_store - - A ``dict`` matching domain keys to evaluable (but non-literal) domains. - - Used to store references to non-literal domains which need to be - round-tripped to the client browser. - """ - def __init__(self, server='127.0.0.1', port=8069, model_factory=OpenERPModel): - self._server = server - self._port = port - self._db = False - self._uid = False - self._login = False - self._password = False - self.model_factory = model_factory - self._locale = 'en_US' - self.context = {} - self.contexts_store = {} - self.domains_store = {} - self._lang = {} - self.remote_timezone = 'utc' - self.client_timezone = False - - def proxy(self, service): - s = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/%s' % (self._server, self._port, service)) - return s - - def bind(self, db, uid, password): - self._db = db - self._uid = uid - self._password = password - - def login(self, db, login, password): - uid = self.proxy('common').login(db, login, password) - self.bind(db, uid, password) - self._login = login - - if uid: self.get_context() - return uid - - def assert_valid(self): - """ - Ensures this session is valid (logged into the openerp server) - """ - if not (self._db and self._uid and self._password): - raise OpenERPUnboundException() - - def execute(self, model, func, *l, **d): - self.assert_valid() - r = self.proxy('object').execute(self._db, self._uid, self._password, model, func, *l, **d) - return r - - def exec_workflow(self, model, id, signal): - self.assert_valid() - r = self.proxy('object').exec_workflow(self._db, self._uid, self._password, model, signal, id) - return r - - def model(self, model): - """ Get an RPC proxy for the object ``model``, bound to this session. - - :param model: an OpenERP model name - :type model: str - :rtype: :class:`openerpweb.openerpweb.OpenERPModel` - """ - return self.model_factory(self, model) - - def get_context(self): - """ Re-initializes the current user's session context (based on - his preferences) by calling res.users.get_context() with the old - context - - :returns: the new context - """ - assert self._uid, "The user needs to be logged-in to initialize his context" - self.context = self.model('res.users').context_get(self.context) - self.context = self.context or {} - - self.client_timezone = self.context.get("tz", False) - # invalid code, anyway we decided the server will be in UTC - #if self.client_timezone: - # self.remote_timezone = self.execute('common', 'timezone_get') - - self._locale = self.context.get('lang','en_US') - lang_ids = self.execute('res.lang','search', [('code', '=', self._locale)]) - if lang_ids: - self._lang = self.execute('res.lang', 'read',lang_ids[0], []) - return self.context - - @property - def base_eval_context(self): - """ Default evaluation context for the session. - - Used to evaluate contexts and domains. - """ - base = dict( - uid=self._uid, - current_date=datetime.date.today().strftime('%Y-%m-%d'), - time=time, - datetime=datetime, - relativedelta=dateutil.relativedelta.relativedelta - ) - base.update(self.context) - return base - - def evaluation_context(self, context=None): - """ Returns the session's evaluation context, augmented with the - provided context if any. - - :param dict context: to add merge in the session's base eval context - :returns: the augmented context - :rtype: dict - """ - d = dict(self.base_eval_context) - if context: - d.update(context) - d['context'] = d - return d - - def eval_context(self, context_to_eval, context=None): - """ Evaluates the provided context_to_eval in the context (haha) of - the context. Also merges the evaluated context with the session's context. - - :param context_to_eval: a context to evaluate. Must be a dict or a - non-literal context. If it's a dict, will be - returned as-is - :type context_to_eval: openerpweb.nonliterals.Context - :returns: the evaluated context - :rtype: dict - - :raises: ``TypeError`` if ``context_to_eval`` is neither a dict nor - a Context - """ - ctx = dict( - self.base_eval_context, - **(context or {})) - - # adding the context of the session to send to the openerp server - ccontext = nonliterals.CompoundContext(self.context, context_to_eval or {}) - ccontext.session = self - return ccontext.evaluate(ctx) - - def eval_domain(self, domain, context=None): - """ Evaluates the provided domain using the provided context - (merged with the session's evaluation context) - - :param domain: an OpenERP domain as a list or as a - :class:`openerpweb.nonliterals.Domain` instance - - In the second case, it will be evaluated and returned. - :type domain: openerpweb.nonliterals.Domain - :param dict context: the context to use in the evaluation, if any. - :returns: the evaluated domain - :rtype: list - - :raises: ``TypeError`` if ``domain`` is neither a list nor a Domain - """ - if isinstance(domain, list): - return domain - - cdomain = nonliterals.CompoundDomain(domain) - cdomain.session = self - return cdomain.evaluate(context or {}) - #---------------------------------------------------------- # OpenERP Web RequestHandler #---------------------------------------------------------- @@ -425,12 +237,16 @@ class Root(object): controllers_path[o._cp_path] = o def default(self, *l, **kw): - #print "default",l,kw + print "default",l,kw # handle static files if len(l) > 2 and l[1] == 'static': # sanitize path p = os.path.normpath(os.path.join(*l)) - return cherrypy.lib.static.serve_file(os.path.join(path_addons, p)) + p2 = os.path.join(path_addons, p) + print "p",p + print "p2",p2 + + return cherrypy.lib.static.serve_file(p2) elif len(l) > 1: for i in range(len(l), 1, -1): ps = "/" + "/".join(l[0:i]) diff --git a/openerpweb/nonliterals.py b/addons/base/common/nonliterals.py similarity index 100% rename from openerpweb/nonliterals.py rename to addons/base/common/nonliterals.py diff --git a/openerpweb/tests/__init__.py b/addons/base/common/tests/__init__.py similarity index 100% rename from openerpweb/tests/__init__.py rename to addons/base/common/tests/__init__.py diff --git a/openerpweb/tests/test_model.py b/addons/base/common/tests/test_model.py similarity index 100% rename from openerpweb/tests/test_model.py rename to addons/base/common/tests/test_model.py diff --git a/openerpweb/tests/test_nonliterals.py b/addons/base/common/tests/test_nonliterals.py similarity index 100% rename from openerpweb/tests/test_nonliterals.py rename to addons/base/common/tests/test_nonliterals.py diff --git a/openerpweb/tests/test_session.py b/addons/base/common/tests/test_session.py similarity index 100% rename from openerpweb/tests/test_session.py rename to addons/base/common/tests/test_session.py diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index c9bd7ddfeab..0d652500a35 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -15,9 +15,11 @@ from cStringIO import StringIO import cherrypy -import openerpweb -import openerpweb.ast -import openerpweb.nonliterals +import base.common as openerpweb +import base.common.ast +import base.common.nonliterals +openerpweb.ast = base.common.ast +openerpweb.nonliterals = base.common.nonliterals from babel.messages.pofile import read_po diff --git a/addons/base/static/src/css/base.css b/addons/base/static/src/css/base.css index b0a7dd3c8c8..a33bdce973b 100644 --- a/addons/base/static/src/css/base.css +++ b/addons/base/static/src/css/base.css @@ -597,13 +597,13 @@ label.error { background-color: #ccc; } .openerp .searchview_group.folded .searchview_group_string { - background: url("../img/ui/group-folded.png") no-repeat scroll 0 50%; + background: url("/base/static/src/img/ui/group-folded.png") no-repeat scroll 0 50%; } .openerp .searchview_group.folded .searchview_group_content { display: none; } .openerp .searchview_group.expanded .searchview_group_string { - background: url("../img/ui/group-expanded.png") no-repeat scroll 0 50%; + background: url("/base/static/src/img/ui/group-expanded.png") no-repeat scroll 0 50%; } .openerp .searchview_group.expanded .searchview_group_content { display: block; @@ -635,13 +635,13 @@ label.error { } .openerp .oe_search-view-custom-filter-btn span { - background: url(../img/icons/gtk-add.png) repeat-y; + background: url(/base/static/src/img/icons/gtk-add.png) repeat-y; padding-left: 18px; } .openerp .searchview_extended_add_proposition span { font-size: 0.9em; - background: url(../img/icons/gtk-add.png) repeat-y; + background: url(/base/static/src/img/icons/gtk-add.png) repeat-y; padding-left: 18px; } @@ -657,7 +657,7 @@ label.error { .openerp .searchview_extended_delete_group span, .openerp .searchview_extended_delete_prop span { font-size: 0.9em; - background: url(../img/icons/gtk-close.png) repeat-y; + background: url(/base/static/src/img/icons/gtk-close.png) repeat-y; padding-left: 18px; } /* List */ @@ -931,6 +931,9 @@ label.error { margin: 3px 4px 3px 1px; height: 15px; } +.openerp .oe_form_frame_cell.oe_form_separator_vertical { + border-left: 1px solid #666; +} .openerp td.required input, .openerp td.required select { background-color: #D2D2FF !important; } @@ -1091,7 +1094,7 @@ label.error { cursor: pointer; border: 1px solid #D2CFCF; display: block; - background: url(../img/toggle-a-bg.png); + background: url(/base/static/src/img/toggle-a-bg.png); width: 21px; height: 21px; z-index: 10; @@ -1106,7 +1109,7 @@ label.error { } .openerp li.oe_sidebar_print { padding-left: 20px; - background: 1px 3px url(../img/icons/gtk-print.png) no-repeat; + background: 1px 3px url(/base/static/src/img/icons/gtk-print.png) no-repeat; } .openerp.kitten-mode-activated .main_table { diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index bf649e5f374..ea24b058573 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -83,9 +83,11 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi this.$form_header.find('button.oe_form_button_cancel').click(this.do_cancel); this.$form_header.find('button.oe_form_button_new').click(this.on_button_new); - this.$form_header.find('button.oe_get_xml_view').click(function() { - $('' + openerp.base.json_node_to_xml(self.fields_view.arch, true) + '').dialog({ width: '95%', height: 600}); - }); + if (this.session.debug) { + this.$form_header.find('button.oe_get_xml_view').click(function() { + $('' + openerp.base.json_node_to_xml(self.fields_view.arch, true) + '').dialog({ width: '95%', height: 600}); + }); + } if (this.options.sidebar && this.options.sidebar_id) { this.sidebar = new openerp.base.Sidebar(this, this.options.sidebar_id); @@ -577,18 +579,23 @@ openerp.base.form.Widget = openerp.base.Widget.extend({ this.view.widgets[this.element_id] = this; this.children = node.children; - this.colspan = parseInt(node.attrs.colspan || 1); + this.colspan = parseInt(node.attrs.colspan || 1, 10); + this.decrease_max_width = 0; this.string = this.string || node.attrs.string; this.help = this.help || node.attrs.help; this.invisible = this.modifiers['invisible'] === true; + this.classname = 'oe_form_' + this.type; + + this.width = this.node.attrs.width; }, start: function() { this.$element = $('#' + this.element_id); }, stop: function() { - this.$element = $('#' + this.element_id); - this.$element.remove(); + if (this.$element) { + this.$element.remove(); + } }, process_modifiers: function() { var compute_domain = openerp.base.form.compute_domain; @@ -609,7 +616,7 @@ openerp.base.form.WidgetFrame = openerp.base.form.Widget.extend({ template: 'WidgetFrame', init: function(view, node) { this._super(view, node); - this.columns = node.attrs.col || 4; + this.columns = parseInt(node.attrs.col || 4, 10); this.x = 0; this.y = 0; this.table = []; @@ -635,15 +642,21 @@ openerp.base.form.WidgetFrame = openerp.base.form.Widget.extend({ return row; }, set_row_cells_with: function(row) { + var bypass = 0, + max_width = 100; + for (var i = 0; i < row.length; i++) { + bypass += row[i].width === undefined ? 0 : 1; + max_width -= row[i].decrease_max_width; + } + var size_unit = Math.round(max_width / (this.columns - bypass)), + colspan_sum = 0; for (var i = 0; i < row.length; i++) { var w = row[i]; - if (w.is_field_label) { - w.width = "1%"; - if (row[i + 1]) { - row[i + 1].width = Math.round((100 / this.columns) * (w.colspan + 1) - 1) + '%'; - } - } else if (w.width === undefined) { - w.width = Math.round((100 / this.columns) * w.colspan) + '%'; + colspan_sum += w.colspan; + if (w.width === undefined) { + var width = (i === row.length - 1 && colspan_sum === this.columns) ? max_width : Math.round(size_unit * w.colspan); + max_width -= width; + w.width = width + '%'; } } }, @@ -733,6 +746,11 @@ openerp.base.form.WidgetSeparator = openerp.base.form.Widget.extend({ init: function(view, node) { this._super(view, node); this.template = "WidgetSeparator"; + this.orientation = node.attrs.orientation || 'horizontal'; + if (this.orientation === 'vertical') { + this.width = '1'; + } + this.classname += '_' + this.orientation; } }); @@ -796,14 +814,15 @@ openerp.base.form.WidgetLabel = openerp.base.form.Widget.extend({ this._super(view, node); // TODO fme: support for attrs.align - if (this.node.tag == 'label' && this.node.attrs.colspan) { - this.is_field_label = false; + if (this.node.tag == 'label' && (this.node.attrs.colspan || (this.string && this.string.length > 32))) { this.template = "WidgetParagraph"; - this.colspan = this.node.attrs.colspan; + this.colspan = parseInt(this.node.attrs.colspan || 1, 10); } else { - this.is_field_label = true; this.template = "WidgetLabel"; this.colspan = 1; + this.width = '1%'; + this.decrease_max_width = 1; + this.nowrap = true; } }, render: function () { @@ -845,6 +864,8 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({ this.required = this.modifiers['required'] === true; this.invalid = false; this.dirty = false; + + this.classname = 'oe_form_field_' + this.type; }, start: function() { this._super.apply(this, arguments); diff --git a/addons/base/static/src/js/formats.js b/addons/base/static/src/js/formats.js index ed25b28c16d..bf54290bf45 100644 --- a/addons/base/static/src/js/formats.js +++ b/addons/base/static/src/js/formats.js @@ -28,8 +28,10 @@ openerp.base.format_value = function (value, descriptor, value_if_empty) { case 'float': var precision = descriptor.digits ? descriptor.digits[1] : 2; var int_part = Math.floor(value); - var dec_part = Math.floor((value % 1) * Math.pow(10, precision)); - return _.sprintf('%d' + openerp.base._t.database.parameters.decimal_point + '%d', int_part, dec_part); + var dec_part = Math.abs(Math.floor((value % 1) * Math.pow(10, precision))); + return _.sprintf('%d%s%d', + int_part, + openerp.base._t.database.parameters.decimal_point, dec_part); case 'float_time': return _.sprintf("%02d:%02d", Math.floor(value), @@ -45,7 +47,7 @@ openerp.base.format_value = function (value, descriptor, value_if_empty) { if (typeof(value) == "string") value = openerp.base.str_to_datetime(value); try { - return value.toString(_.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, + return value.toString(_.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, Date.CultureInfo.formatPatterns.longTime)); } catch (e) { return value.format("%m/%d/%Y %H:%M:%S"); @@ -108,7 +110,7 @@ openerp.base.parse_value = function (value, descriptor, value_if_empty) { case 'progressbar': return openerp.base.parse_value(value, {type: "float"}); case 'datetime': - var tmp = Date.parseExact(value, _.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, + var tmp = Date.parseExact(value, _.sprintf("%s %s", Date.CultureInfo.formatPatterns.shortDate, Date.CultureInfo.formatPatterns.longTime)); if (tmp !== null) return tmp; @@ -117,7 +119,7 @@ openerp.base.parse_value = function (value, descriptor, value_if_empty) { return tmp; throw value + " is not a valid datetime"; case 'date': - var tmp = Date.parseExact(Date.CultureInfo.formatPatterns.shortDate); + var tmp = Date.parseExact(value, Date.CultureInfo.formatPatterns.shortDate); if (tmp !== null) return tmp; tmp = Date.parse(value); @@ -125,7 +127,7 @@ openerp.base.parse_value = function (value, descriptor, value_if_empty) { return tmp; throw value + " is not a valid date"; case 'time': - var tmp = Date.parseExact(Date.CultureInfo.formatPatterns.longTime); + var tmp = Date.parseExact(value, Date.CultureInfo.formatPatterns.longTime); if (tmp !== null) return tmp; tmp = Date.parse(value); diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml index c6bd9a1ee19..b308d1c7856 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -622,7 +622,7 @@
-

+

- + + + + + diff --git a/addons/base_calendar/controllers/main.py b/addons/base_calendar/controllers/main.py index 28c871bf2b4..0211b3e4632 100644 --- a/addons/base_calendar/controllers/main.py +++ b/addons/base_calendar/controllers/main.py @@ -1,5 +1,6 @@ +import base.common as openerpweb + from base.controllers.main import View -import openerpweb class CalendarView(View): _cp_path = "/base_calendar/calendarview" diff --git a/addons/base_dashboard/controllers.py b/addons/base_dashboard/controllers.py index b0f5fbf817e..2ebfefab1e8 100644 --- a/addons/base_dashboard/controllers.py +++ b/addons/base_dashboard/controllers.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -import openerpweb +import base.common as openerpweb WIDGET_CONTENT_PATTERN = """ @@ -18,7 +18,7 @@ WIDGET_CONTENT_PATTERN = """ """ -class Widgets(openerpweb.openerpweb.Controller): +class Widgets(openerpweb.Controller): _cp_path = '/base_dashboard/widgets' @openerpweb.httprequest diff --git a/addons/base_diagram/controllers/main.py b/addons/base_diagram/controllers/main.py index 2f76ead7117..8e258810eca 100644 --- a/addons/base_diagram/controllers/main.py +++ b/addons/base_diagram/controllers/main.py @@ -1,5 +1,5 @@ +import base.common as openerpweb from base.controllers.main import View -import openerpweb class DiagramView(View): _cp_path = "/base_diagram/diagram" diff --git a/addons/base_gantt/controllers/main.py b/addons/base_gantt/controllers/main.py index 0e6754ecb05..56fb2b7e79f 100644 --- a/addons/base_gantt/controllers/main.py +++ b/addons/base_gantt/controllers/main.py @@ -1,4 +1,4 @@ -import openerpweb +import base.common as openerpweb from base.controllers.main import View class GanttView(View): diff --git a/addons/base_graph/controllers/main.py b/addons/base_graph/controllers/main.py index 680b9e030c2..f326faf3854 100644 --- a/addons/base_graph/controllers/main.py +++ b/addons/base_graph/controllers/main.py @@ -1,5 +1,5 @@ from base.controllers.main import View -import openerpweb +import base.common as openerpweb class GraphView(View): _cp_path = "/base_graph/graphview" @@ -8,4 +8,4 @@ class GraphView(View): def load(self, req, model, view_id): fields_view = self.fields_view_get(req, model, view_id, 'graph') all_fields = req.session.model(model).fields_get() - return {'fields_view': fields_view, 'all_fields':all_fields} \ No newline at end of file + return {'fields_view': fields_view, 'all_fields':all_fields} diff --git a/addons/web_chat/controllers/main.py b/addons/web_chat/controllers/main.py index 5e8d48344f8..5c427812d47 100644 --- a/addons/web_chat/controllers/main.py +++ b/addons/web_chat/controllers/main.py @@ -4,7 +4,7 @@ import cherrypy import simplejson import random -import openerpweb +import base.common as openerpweb #---------------------------------------------------------- # OpenERP Web ajaxim Controllers diff --git a/addons/web_mobile/controllers/main.py b/addons/web_mobile/controllers/main.py index d2ba132d1c2..8fa3e32a775 100644 --- a/addons/web_mobile/controllers/main.py +++ b/addons/web_mobile/controllers/main.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- -import glob, os -import pprint - -import simplejson - -import openerpweb -import openerpweb.ast -import openerpweb.nonliterals - -import cherrypy - +#import glob, os +#import pprint +# +#import simplejson +# +#import openerpweb +#import openerpweb.ast +#import openerpweb.nonliterals +# +#import cherrypy +# diff --git a/openerp-web.py b/openerp-web.py index 99305b276a8..3363b4466a7 100755 --- a/openerp-web.py +++ b/openerp-web.py @@ -1,7 +1,20 @@ #!/usr/bin/env python -import sys +import os,sys -import openerpweb +path_root = os.path.dirname(os.path.abspath(__file__)) +path_addons = os.path.join(path_root, 'addons') +if path_addons not in sys.path: + sys.path.insert(0, path_addons) + +import base + +def main(): + # TODO move the code of base.common.main here ! + # change the code to configure a simple werzug server -> base.common.Root() + base.common.main(sys.argv) if __name__ == "__main__": - openerpweb.main(sys.argv) + main() + + + diff --git a/openerpweb/__init__.py b/openerpweb/__init__.py deleted file mode 100644 index b201d5a7953..00000000000 --- a/openerpweb/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/python -from openerpweb import *