[MERGE] Merge from openerp-web.
bzr revid: jra@tinyerp.com-20110831062056-oftc3hgx8297sfhj
This commit is contained in:
commit
f9a31ab33e
|
@ -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])
|
|
@ -9,17 +9,22 @@ import re
|
|||
import simplejson
|
||||
import textwrap
|
||||
import xmlrpclib
|
||||
import time
|
||||
from xml.etree import ElementTree
|
||||
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
|
||||
|
||||
_REPORT_POLLER_DELAY = 0.05
|
||||
|
||||
# Should move to openerpweb.Xml2Json
|
||||
class Xml2Json:
|
||||
# xml2json-direct
|
||||
|
@ -432,9 +437,12 @@ def load_actions_from_ir_values(req, key, key2, models, meta):
|
|||
for id, name, action in actions]
|
||||
|
||||
def clean_action(req, action):
|
||||
action.setdefault('flags', {})
|
||||
if action['type'] != 'ir.actions.act_window':
|
||||
return action
|
||||
|
||||
context = req.session.eval_context(req.context)
|
||||
eval_ctx = req.session.evaluation_context(context)
|
||||
action.setdefault('flags', {})
|
||||
|
||||
# values come from the server, we can just eval them
|
||||
if isinstance(action.get('context'), basestring):
|
||||
|
@ -1272,3 +1280,25 @@ class Export(View):
|
|||
return export_xls(field, result)
|
||||
else:
|
||||
return export_csv(field, result)
|
||||
|
||||
class Export(View):
|
||||
_cp_path = "/base/report"
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get_report(self, req, action):
|
||||
report_srv = req.session.proxy("report")
|
||||
context = req.session.eval_context(openerpweb.nonliterals.CompoundContext(req.context, \
|
||||
action["context"]))
|
||||
|
||||
args = [req.session._db, req.session._uid, req.session._password, action["report_name"], context["active_ids"], {"id": context["active_id"], "model": context["active_model"], "report_type": action["report_type"]}, context]
|
||||
report_id = report_srv.report(*args)
|
||||
report = None
|
||||
while True:
|
||||
args2 = [req.session._db, req.session._uid, req.session._password, report_id]
|
||||
report = report_srv.report_get(*args2)
|
||||
if report["state"]:
|
||||
break
|
||||
time.sleep(_REPORT_POLLER_DELAY)
|
||||
|
||||
#TODO: ok now we've got the report, and so what?
|
||||
return False
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
if(!menu) {
|
||||
menu=$('<div id="jqContextMenu"></div>').hide().css({
|
||||
position:'absolute',
|
||||
zIndex:'500'
|
||||
zIndex:'2000'
|
||||
}).appendTo('body').bind('click', function(e) {
|
||||
e.stopPropagation()
|
||||
})
|
||||
|
|
|
@ -895,6 +895,9 @@ label.error {
|
|||
position: relative;
|
||||
top: 4px;
|
||||
}
|
||||
.openerp .oe_trad_field.touched {
|
||||
border: 1px solid green !important;
|
||||
}
|
||||
|
||||
/* http://www.quirksmode.org/dom/inputfile.html
|
||||
* http://stackoverflow.com/questions/2855589/replace-input-type-file-by-an-image
|
||||
|
|
|
@ -479,8 +479,6 @@ openerp.base.Login = openerp.base.Widget.extend({
|
|||
this.selected_login = localStorage.getItem('last_login_login_success');
|
||||
}
|
||||
if (jQuery.deparam(jQuery.param.querystring()).debug != undefined) {
|
||||
this.selected_db = this.selected_db || "trunk";
|
||||
this.selected_login = this.selected_login || "admin";
|
||||
this.selected_password = this.selected_password || "a";
|
||||
}
|
||||
},
|
||||
|
@ -564,22 +562,25 @@ openerp.base.Login = openerp.base.Widget.extend({
|
|||
});
|
||||
|
||||
openerp.base.Header = openerp.base.Widget.extend({
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
if (jQuery.deparam(jQuery.param.querystring()).debug !== undefined) {
|
||||
this.qs = '?debug'
|
||||
} else {
|
||||
this.qs = ''
|
||||
}
|
||||
template: "Header",
|
||||
identifier_prefix: 'oe-app-header-',
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
this.qs = "?" + jQuery.param.querystring();
|
||||
this.$content = $();
|
||||
},
|
||||
start: function() {
|
||||
return this.do_update();
|
||||
this._super();
|
||||
},
|
||||
do_update: function () {
|
||||
this.$element.html(QWeb.render("Header", this));
|
||||
this.$content = $(QWeb.render("Header-content", {widget: this}));
|
||||
this.$content.appendTo(this.$element);
|
||||
this.$element.find(".logout").click(this.on_logout);
|
||||
return this.shortcut_load();
|
||||
},
|
||||
do_reset: function() {
|
||||
this.$content.remove();
|
||||
},
|
||||
shortcut_load :function(){
|
||||
var self = this,
|
||||
sc = self.session.shortcuts,
|
||||
|
@ -749,21 +750,23 @@ openerp.base.WebClient = openerp.base.Widget.extend({
|
|||
// Do you autorize this ? will be replaced by notify() in controller
|
||||
openerp.base.Widget.prototype.notification = new openerp.base.Notification(this, "oe_notification");
|
||||
|
||||
this.header = new openerp.base.Header(this, "oe_header");
|
||||
|
||||
this.header = new openerp.base.Header(this);
|
||||
this.login = new openerp.base.Login(this, "oe_login");
|
||||
this.header.on_logout.add(this.login.on_logout);
|
||||
this.header.on_action.add(this.on_menu_action);
|
||||
|
||||
this.session.on_session_invalid.add(this.login.do_ask_login);
|
||||
this.session.on_session_valid.add_last(this.header.do_update);
|
||||
this.session.on_session_invalid.add_last(this.header.do_reset);
|
||||
this.session.on_session_valid.add_last(this.on_logged);
|
||||
|
||||
this.menu = new openerp.base.Menu(this, "oe_menu", "oe_secondary_menu");
|
||||
this.menu.on_action.add(this.on_menu_action);
|
||||
this.header.on_action.add(this.on_menu_action);
|
||||
},
|
||||
start: function() {
|
||||
this.header.appendTo($("#oe_header"));
|
||||
this.session.start();
|
||||
this.header.start();
|
||||
this.login.start();
|
||||
this.menu.start();
|
||||
this.notification.notify("OpenERP Client", "The openerp client has been initialized.");
|
||||
|
|
|
@ -355,12 +355,13 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
|||
* @param {Function} error_callback function called in case of write error
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
write: function (id, data, callback, error_callback) {
|
||||
write: function (id, data, options, callback, error_callback) {
|
||||
var options = options || {};
|
||||
return this.rpc('/base/dataset/save', {
|
||||
model: this.model,
|
||||
id: id,
|
||||
data: data,
|
||||
context: this.get_context()
|
||||
context: this.get_context(options.context)
|
||||
}, callback, error_callback);
|
||||
},
|
||||
/**
|
||||
|
|
|
@ -157,6 +157,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi
|
|||
this.do_update_pager(record.id == null);
|
||||
if (this.sidebar) {
|
||||
this.sidebar.attachments.do_update();
|
||||
this.sidebar.$element.find('.oe_sidebar_translate').toggleClass('oe_hide', !record.id);
|
||||
}
|
||||
if (this.default_focus_field && !this.embedded_view) {
|
||||
this.default_focus_field.focus();
|
||||
|
@ -342,7 +343,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi
|
|||
self.on_created(r, success, prepend_on_create);
|
||||
});
|
||||
} else {
|
||||
return this.dataset.write(this.datarecord.id, values, function(r) {
|
||||
return this.dataset.write(this.datarecord.id, values, {}, function(r) {
|
||||
self.on_saved(r, success);
|
||||
});
|
||||
}
|
||||
|
@ -879,6 +880,9 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({
|
|||
},
|
||||
update_dom: function() {
|
||||
this._super.apply(this, arguments);
|
||||
if (this.field.translate) {
|
||||
this.$element.find('.oe_field_translate').toggle(!!this.view.datarecord.id);
|
||||
}
|
||||
if (!this.disable_utility_classes) {
|
||||
this.$element.toggleClass('disabled', this.readonly);
|
||||
this.$element.toggleClass('required', this.required);
|
||||
|
@ -1519,12 +1523,14 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
|||
},
|
||||
set_value: function(value) {
|
||||
value = value || null;
|
||||
this.invalid = false;
|
||||
var self = this;
|
||||
var _super = this._super;
|
||||
this.tmp_value = value;
|
||||
self.update_dom();
|
||||
self.on_value_changed();
|
||||
var real_set_value = function(rval) {
|
||||
self.tmp_value = undefined;
|
||||
_super.apply(self, rval);
|
||||
self.value = rval;
|
||||
self.original_value = undefined;
|
||||
self._change_int_ext_value(rval);
|
||||
};
|
||||
|
@ -1550,7 +1556,8 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
|||
},
|
||||
validate: function() {
|
||||
this.invalid = false;
|
||||
if (this.value === null) {
|
||||
var val = this.tmp_value !== undefined ? this.tmp_value : this.value;
|
||||
if (val === null) {
|
||||
this.invalid = this.required;
|
||||
}
|
||||
},
|
||||
|
@ -1558,14 +1565,16 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
|||
var self = this;
|
||||
if (!self.value)
|
||||
return;
|
||||
self.rpc("/base/action/load", {
|
||||
action_id: related[2].id,
|
||||
context: {
|
||||
var additional_context = {
|
||||
active_id: self.value[0],
|
||||
active_ids: [self.value[0]],
|
||||
active_model: self.field.relation
|
||||
}
|
||||
};
|
||||
self.rpc("/base/action/load", {
|
||||
action_id: related[2].id,
|
||||
context: additional_context
|
||||
}, function(result) {
|
||||
result.result.context = _.extend(result.result.context || {}, additional_context);
|
||||
self.do_action(result.result);
|
||||
});
|
||||
}
|
||||
|
@ -1863,10 +1872,13 @@ openerp.base.form.One2ManyListView = openerp.base.ListView.extend({
|
|||
pop.show_element(self.o2m.field.relation, id, self.o2m.build_context(),{
|
||||
auto_write: false,
|
||||
alternative_form_view: self.o2m.field.views ? self.o2m.field.views["form"] : undefined,
|
||||
parent_view: self.o2m.view
|
||||
parent_view: self.o2m.view,
|
||||
read_function: function() {
|
||||
return self.o2m.dataset.read_ids.apply(self.o2m.dataset, arguments);
|
||||
}
|
||||
});
|
||||
pop.on_write.add(function(id, data) {
|
||||
self.o2m.dataset.write(id, data, function(r) {
|
||||
self.o2m.dataset.write(id, data, {}, function(r) {
|
||||
self.o2m.reload_current_view();
|
||||
});
|
||||
});
|
||||
|
@ -2135,6 +2147,7 @@ openerp.base.form.FormOpenPopup = openerp.base.OldWidget.extend({
|
|||
* options:
|
||||
* - alternative_form_view
|
||||
* - auto_write (default true)
|
||||
* - read_function
|
||||
* - parent_view
|
||||
*/
|
||||
show_element: function(model, row_id, context, options) {
|
||||
|
@ -2150,7 +2163,8 @@ openerp.base.form.FormOpenPopup = openerp.base.OldWidget.extend({
|
|||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
this.dataset = new openerp.base.ReadOnlyDataSetSearch(this, this.model, this.context);
|
||||
this.dataset = new openerp.base.form.FormOpenDataset(this, this.model, this.context);
|
||||
this.dataset.fop = this;
|
||||
this.dataset.ids = [this.row_id];
|
||||
this.dataset.index = 0;
|
||||
this.dataset.parent_view = this.options.parent_view;
|
||||
|
@ -2163,7 +2177,7 @@ openerp.base.form.FormOpenPopup = openerp.base.OldWidget.extend({
|
|||
var self = this;
|
||||
var wdataset = new openerp.base.DataSetSearch(this, this.model, this.context, this.domain);
|
||||
wdataset.parent_view = this.options.parent_view;
|
||||
wdataset.write(id, data, function(r) {
|
||||
wdataset.write(id, data, {}, function(r) {
|
||||
self.on_write_completed();
|
||||
});
|
||||
},
|
||||
|
@ -2192,6 +2206,16 @@ openerp.base.form.FormOpenPopup = openerp.base.OldWidget.extend({
|
|||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FormOpenDataset = openerp.base.ReadOnlyDataSetSearch.extend({
|
||||
read_ids: function() {
|
||||
if (this.fop.options.read_function) {
|
||||
return this.fop.options.read_function.apply(null, arguments);
|
||||
} else {
|
||||
return this._super.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldReference = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
|
|
|
@ -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, dec_part,
|
||||
openerp.base._t.database.parameters.decimal_point);
|
||||
case 'float_time':
|
||||
return _.sprintf("%02d:%02d",
|
||||
Math.floor(value),
|
||||
|
|
|
@ -123,6 +123,14 @@ openerp.base.ActionManager = openerp.base.Widget.extend({
|
|||
this.content_stop();
|
||||
var ClientWidget = openerp.base.client_actions.get_object(action.tag);
|
||||
(this.client_widget = new ClientWidget(this, action.params)).appendTo(this);
|
||||
},
|
||||
ir_actions_report_xml: function(action) {
|
||||
this.rpc('/base/report/get_report', {
|
||||
action: action,
|
||||
context: {}
|
||||
}).then(function(result) {
|
||||
debugger;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -438,14 +446,17 @@ openerp.base.Sidebar = openerp.base.Widget.extend({
|
|||
//TODO niv: maybe show a warning?
|
||||
return false;
|
||||
}
|
||||
self.rpc("/base/action/load", {
|
||||
action_id: item.action.id,
|
||||
context: {
|
||||
var additional_context = {
|
||||
active_id: ids[0],
|
||||
active_ids: ids,
|
||||
active_model: self.widget_parent.dataset.model
|
||||
}
|
||||
};
|
||||
self.rpc("/base/action/load", {
|
||||
action_id: item.action.id,
|
||||
context: additional_context
|
||||
}, function(result) {
|
||||
result.result.context = _.extend(result.result.context || {},
|
||||
additional_context);
|
||||
result.result.flags = result.result.flags || {};
|
||||
result.result.flags.new_window = true;
|
||||
self.do_action(result.result);
|
||||
|
@ -472,6 +483,9 @@ openerp.base.Sidebar = openerp.base.Widget.extend({
|
|||
openerp.base.TranslateDialog = openerp.base.Dialog.extend({
|
||||
dialog_title: _t("Translations"),
|
||||
init: function(view) {
|
||||
// TODO fme: should add the language to fields_view_get because between the fields view get
|
||||
// and the moment the user opens the translation dialog, the user language could have been changed
|
||||
this.view_language = view.session.user_context.lang;
|
||||
this['on_button' + _t("Save")] = this.on_button_Save;
|
||||
this['on_button' + _t("Close")] = this.on_button_Close;
|
||||
this._super(view, {
|
||||
|
@ -500,6 +514,9 @@ openerp.base.TranslateDialog = openerp.base.Dialog.extend({
|
|||
self.select_tab('view');
|
||||
}
|
||||
self.$fields_form = self.$element.find('.oe_translation_form');
|
||||
self.$fields_form.find('.oe_trad_field').change(function() {
|
||||
$(this).toggleClass('touched', ($(this).val() != $(this).attr('data-value')));
|
||||
});
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
@ -514,19 +531,27 @@ openerp.base.TranslateDialog = openerp.base.Dialog.extend({
|
|||
_.each(self.languages, function(lg) {
|
||||
var deff = $.Deferred();
|
||||
deffered.push(deff);
|
||||
var callback = function(values) {
|
||||
_.each(self.translatable_fields_keys, function(f) {
|
||||
self.$fields_form.find('.oe_trad_field[name="' + lg.code + '-' + f + '"]').val(values[0][f] || '').attr('data-value', values[0][f] || '');
|
||||
});
|
||||
deff.resolve();
|
||||
}
|
||||
if (lg.code === self.view_language) {
|
||||
var values = {};
|
||||
_.each(self.translatable_fields_keys, function(field) {
|
||||
values[field] = self.view.fields[field].get_value();
|
||||
});
|
||||
callback([values]);
|
||||
} else {
|
||||
self.rpc('/base/dataset/get', {
|
||||
model: self.view.dataset.model,
|
||||
ids: [self.view.datarecord.id],
|
||||
fields: self.translatable_fields_keys,
|
||||
context: self.view.dataset.get_context({
|
||||
'lang': lg.code
|
||||
})
|
||||
}, function(values) {
|
||||
_.each(self.translatable_fields_keys, function(f) {
|
||||
self.$fields_form.find('.oe_trad_field[name="' + lg.code + '-' + f + '"]').val(values[0][f] || '');
|
||||
});
|
||||
deff.resolve();
|
||||
});
|
||||
})}, callback);
|
||||
}
|
||||
});
|
||||
$.when.apply(null, deffered).then(callback);
|
||||
},
|
||||
|
@ -562,6 +587,24 @@ openerp.base.TranslateDialog = openerp.base.Dialog.extend({
|
|||
});
|
||||
},
|
||||
on_button_Save: function() {
|
||||
var trads = {},
|
||||
self = this;
|
||||
self.$fields_form.find('.oe_trad_field.touched').each(function() {
|
||||
var field = $(this).attr('name').split('-');
|
||||
if (!trads[field[0]]) {
|
||||
trads[field[0]] = {};
|
||||
}
|
||||
trads[field[0]][field[1]] = $(this).val();
|
||||
});
|
||||
_.each(trads, function(data, code) {
|
||||
if (code === self.view_language) {
|
||||
_.each(data, function(value, field) {
|
||||
self.view.fields[field].set_value(value);
|
||||
});
|
||||
} else {
|
||||
self.view.dataset.write(self.view.datarecord.id, data, { 'lang': code });
|
||||
}
|
||||
});
|
||||
this.close();
|
||||
},
|
||||
on_button_Close: function() {
|
||||
|
@ -667,7 +710,7 @@ openerp.base.View = openerp.base.Widget.extend({
|
|||
}, {
|
||||
label: "Translate",
|
||||
callback: this.on_sidebar_translate,
|
||||
classname: 'oe_sidebar_translate'
|
||||
classname: 'oe_sidebar_translate oe_hide'
|
||||
}, {
|
||||
label: "View Log",
|
||||
callback: this.on_sidebar_view_log,
|
||||
|
|
|
@ -326,15 +326,19 @@
|
|||
</div>
|
||||
</t>
|
||||
<t t-name="Header">
|
||||
<a t-att-href="'/' + qs" class="company_logo_link">
|
||||
<div>
|
||||
<a t-att-href="'/' + widget.qs" class="company_logo_link">
|
||||
<div class="company_logo" />
|
||||
</a>
|
||||
<h1 class="header_title" t-if="session.session_is_valid()">
|
||||
<span class="database"><t t-esc="session.db"/></span> - <t t-esc="session.login"/> <br/>
|
||||
<small class="username">rpc_session_id: <t t-esc="session.session_id"/></small>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="Header-content">
|
||||
<h1 class="header_title">
|
||||
<span class="database"><t t-esc="widget.session.db"/></span> - <t t-esc="widget.session.login"/> <br/>
|
||||
<small class="username">rpc_session_id: <t t-esc="widget.session.session_id"/></small>
|
||||
</h1>
|
||||
<div class="header_corner">
|
||||
<ul class="block" t-if="session.session_is_valid()">
|
||||
<ul class="block">
|
||||
<li>
|
||||
<a href="#home" title="Home" class="home"><img src="/base/static/src/img/header-home.png" width="16" height="16" border="0"/></a>
|
||||
</li>
|
||||
|
@ -474,8 +478,8 @@
|
|||
<label class="oe_form_label"><t t-esc="field.string"/>:</label>
|
||||
</td>
|
||||
<td t-foreach="widget.languages" t-as="lg" class="oe_form_frame_cell">
|
||||
<input t-if="field.type == 'char'" type="text" t-attf-name="#{lg.code}-#{field.name}" value="" class="oe_trad_field" style="width: 100%"/>
|
||||
<textarea t-if="field.type == 'text'" t-attf-name="#{lg.code}-#{field.name}" class="oe_trad_field" style="width: 100%"></textarea>
|
||||
<input t-if="field.type == 'char'" type="text" t-attf-name="#{lg.code}-#{field.name}" value="" data-value="" class="oe_trad_field" style="width: 100%"/>
|
||||
<textarea t-if="field.type == 'text'" t-attf-name="#{lg.code}-#{field.name}" data-value="" class="oe_trad_field" style="width: 100%"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -251,7 +251,7 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
|||
do_save_event: function(event_id, event_obj) {
|
||||
var self = this,
|
||||
data = this.get_event_data(event_obj);
|
||||
this.dataset.write(parseInt(event_id, 10), data, function() {
|
||||
this.dataset.write(parseInt(event_id, 10), data, {}, function() {
|
||||
self.refresh_minical();
|
||||
});
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -327,7 +327,7 @@ openerp.base_dashboard.ConfigOverview = openerp.base.View.extend({
|
|||
e.stopImmediatePropagation();
|
||||
var new_state = this.checked ? 'done' : 'open',
|
||||
todo_id = parseInt($(this).val(), 10);
|
||||
self.dataset.write(todo_id, {state: new_state}, function () {
|
||||
self.dataset.write(todo_id, {state: new_state}, {}, function () {
|
||||
self.start();
|
||||
});
|
||||
})
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -459,7 +459,7 @@ init: function(parent, element_id, dataset, view_id) {
|
|||
}else{
|
||||
data[this.date_delay] = task.getDuration();
|
||||
}
|
||||
this.dataset.write(event_id, data, function(result) {});
|
||||
this.dataset.write(event_id, data, {}, function(result) {});
|
||||
|
||||
},
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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 *
|
Loading…
Reference in New Issue