[MERGE] Merge with trunk
bzr revid: fme@openerp.com-20110831134044-y7f0fmhzndpw6qt9
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
# TODO if from openerpserver use backendlocal
|
||||
# from backendlocal import *
|
||||
from backendrpc import *
|
||||
from dispatch import *
|
||||
@@ -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
|
||||
@@ -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 {})
|
||||
@@ -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])
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
$('<xmp>' + openerp.base.json_node_to_xml(self.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600});
|
||||
});
|
||||
if (this.session.debug) {
|
||||
this.$form_header.find('button.oe_get_xml_view').click(function() {
|
||||
$('<xmp>' + openerp.base.json_node_to_xml(self.fields_view.arch, true) + '</xmp>').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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -622,7 +622,7 @@
|
||||
</t>
|
||||
<t t-name="FormView">
|
||||
<div class="oe_form_header" t-att-id="view.element_id + '_header'">
|
||||
<h2 class="oe_view_title"><t t-esc="view.fields_view.arch.attrs.string"/> <button class="oe_get_xml_view">xml</button></h2>
|
||||
<h2 class="oe_view_title"><t t-esc="view.fields_view.arch.attrs.string"/> <button t-if="view.session.debug" class="oe_get_xml_view">View#<t t-esc="view.fields_view.view_id"/></button></h2>
|
||||
<div class="oe_form_buttons" t-if="view.options.action_buttons !== false">
|
||||
<!--<button type="button" class="oe_form_button_save">
|
||||
<span class="oe_form_on_update">Save</span>
|
||||
@@ -690,11 +690,11 @@
|
||||
<tr t-foreach="widget.table" t-as="row">
|
||||
<t t-foreach="row" t-as="td">
|
||||
<td t-att-colspan="td.colspan gt 1 ? td.colspan : undefined"
|
||||
t-att-width="td.width ? td.width : undefined"
|
||||
t-att-nowrap="td.is_field_label or td.is_field_m2o? 'true' : undefined"
|
||||
t-att-width="td.width"
|
||||
t-att-nowrap="td.nowrap or td.is_field_m2o? 'true' : undefined"
|
||||
t-att-valign="td.table ? 'top' : undefined"
|
||||
t-att-id="td.element_id"
|
||||
t-att-class="'oe_form_frame_cell oe_form_' + (td.is_field_label ? 'label' : (td.field ? 'field_' + td.type : td.type))"
|
||||
t-attf-class="oe_form_frame_cell #{td.classname}"
|
||||
>
|
||||
<t t-raw="td.render()"/>
|
||||
</td>
|
||||
@@ -720,7 +720,7 @@
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="WidgetSeparator">
|
||||
<div t-att-class="'separator ' + (widget.node.attrs.orientation || 'horizontal')">
|
||||
<div t-if="widget.orientation !== 'vertical'" t-att-class="'separator ' + widget.orientation">
|
||||
<t t-esc="widget.string"/>
|
||||
</div>
|
||||
</t>
|
||||
@@ -861,7 +861,8 @@
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<img src="/base/static/src/img/placeholder.png" class="oe-binary-image" border="1"
|
||||
<img src="/base/static/src/img/placeholder.png" class="oe-binary-image"
|
||||
t-att-border="widget.readonly ? 0 : 1"
|
||||
t-att-id="widget.element_id + '_field'"
|
||||
t-att-name="widget.name"
|
||||
t-att-class="'field_' + widget.type"
|
||||
|
||||
@@ -11,17 +11,17 @@ $(document).ready(function () {
|
||||
test("format_datetime", function () {
|
||||
var date = openerp.base.str_to_datetime("2009-05-04 12:34:23");
|
||||
var str = openerp.base.format_value(date, {type:"datetime"});
|
||||
equal(str, date.format("%m/%d/%Y %H:%M:%S"));
|
||||
equal(str, date.toString("M/d/yyyy h:mm:ss tt"));
|
||||
});
|
||||
test("format_date", function () {
|
||||
var date = openerp.base.str_to_datetime("2009-05-04 12:34:23");
|
||||
var str = openerp.base.format_value(date, {type:"date"});
|
||||
equal(str, date.format("%m/%d/%Y"));
|
||||
equal(str, date.toString("M/d/yyyy"));
|
||||
});
|
||||
test("format_time", function () {
|
||||
var date = openerp.base.str_to_datetime("2009-05-04 12:34:23");
|
||||
var str = openerp.base.format_value(date, {type:"time"});
|
||||
equal(str, date.format("%H:%M:%S"));
|
||||
equal(str, date.toString("h:mm:ss tt"));
|
||||
});
|
||||
test("format_float", function () {
|
||||
var fl = 12.1234;
|
||||
@@ -30,22 +30,25 @@ $(document).ready(function () {
|
||||
});
|
||||
test("parse_datetime", function () {
|
||||
var val = openerp.base.str_to_datetime("2009-05-04 12:34:23");
|
||||
var res = openerp.base.parse_value(val.format("%m/%d/%Y %H:%M:%S"), {type:"datetime"});
|
||||
equal(val.format("%m/%d/%Y %H:%M:%S"), res.format("%m/%d/%Y %H:%M:%S"));
|
||||
var res = openerp.base.parse_value(val.toString("M/d/yyyy h:mm:ss tt"), {type:"datetime"});
|
||||
equal(val.toString("M/d/yyyy h:mm:ss tt"), res.toString("M/d/yyyy h:mm:ss tt"));
|
||||
});
|
||||
test("parse_date", function () {
|
||||
var val = openerp.base.str_to_date("2009-05-04");
|
||||
var res = openerp.base.parse_value(val.format("%m/%d/%Y"), {type:"date"});
|
||||
equal(val.format("%m/%d/%Y %H:%M:%S"), res.format("%m/%d/%Y %H:%M:%S"));
|
||||
var res = openerp.base.parse_value(val.toString("M/d/yyyy"), {type:"date"});
|
||||
equal(val.toString("M/d/yyyy"), res.toString("M/d/yyyy"));
|
||||
});
|
||||
test("parse_time", function () {
|
||||
var val = openerp.base.str_to_time("12:34:23");
|
||||
var res = openerp.base.parse_value(val.format("%H:%M:%S"), {type:"time"});
|
||||
equal(val.format("%m/%d/%Y %H:%M:%S"), res.format("%m/%d/%Y %H:%M:%S"));
|
||||
var res = openerp.base.parse_value(val.toString("h:mm:ss tt"), {type:"time"});
|
||||
equal(val.toString("h:mm:ss tt"), res.toString("h:mm:ss tt"));
|
||||
});
|
||||
test("parse_float", function () {
|
||||
var str = "134,112.1234";
|
||||
var val = openerp.base.parse_value(str, {type:"float"});
|
||||
equal(val, 134112.1234);
|
||||
var str = "-134,112.1234";
|
||||
var val = openerp.base.parse_value(str, {type:"float"});
|
||||
equal(val, -134112.1234);
|
||||
});
|
||||
});
|
||||
@@ -14,7 +14,11 @@
|
||||
<!-- jquery -->
|
||||
<script src="/base/static/lib/jquery/jquery-1.6.2.js"></script>
|
||||
<script src="/base/static/lib/jquery.ui/js/jquery-ui-1.8.9.custom.min.js"></script>
|
||||
<script src="/base/static/lib/datejs/date-en-US.js"></script>
|
||||
|
||||
<script src="/base/static/lib/datejs/globalization/en-US.js"></script>
|
||||
<script src="/base/static/lib/datejs/core.js"></script>
|
||||
<script src="/base/static/lib/datejs/parser.js"></script>
|
||||
<script src="/base/static/lib/datejs/sugarpak.js"></script>
|
||||
<script src="/base/static/lib/datejs/extras.js"></script>
|
||||
|
||||
<script src="/base/static/lib/qweb/qweb.js"></script>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import openerpweb
|
||||
import base.common as openerpweb
|
||||
|
||||
WIDGET_CONTENT_PATTERN = """<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -18,7 +18,7 @@ WIDGET_CONTENT_PATTERN = """<!DOCTYPE html>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
class Widgets(openerpweb.openerpweb.Controller):
|
||||
class Widgets(openerpweb.Controller):
|
||||
_cp_path = '/base_dashboard/widgets'
|
||||
|
||||
@openerpweb.httprequest
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import openerpweb
|
||||
import base.common as openerpweb
|
||||
from base.controllers.main import View
|
||||
|
||||
class GanttView(View):
|
||||
|
||||
@@ -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}
|
||||
return {'fields_view': fields_view, 'all_fields':all_fields}
|
||||
|
||||
@@ -4,7 +4,7 @@ import cherrypy
|
||||
|
||||
import simplejson
|
||||
import random
|
||||
import openerpweb
|
||||
import base.common as openerpweb
|
||||
|
||||
#----------------------------------------------------------
|
||||
# OpenERP Web ajaxim Controllers
|
||||
|
||||
@@ -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
|
||||
#
|
||||
|
||||
+16
-3
@@ -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()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from openerpweb import *
|
||||
Reference in New Issue
Block a user