bzr revid: nicolas.vanhoren@openerp.com-20120120130659-rawyshnhas9yflw1
This commit is contained in:
niv-openerp 2012-01-20 14:06:59 +01:00
commit 1a1a77afef
13 changed files with 186 additions and 94 deletions

View File

@ -3,6 +3,7 @@
# OpenERP Web HTTP layer
#----------------------------------------------------------
import ast
import cgi
import contextlib
import functools
import logging
@ -92,7 +93,9 @@ class WebRequest(object):
self.params = dict(params)
# OpenERP session setup
self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex
self.session = self.httpsession.setdefault(self.session_id, session.OpenERPSession())
self.session = self.httpsession.get(self.session_id)
if not self.session:
self.httpsession[self.session_id] = self.session = session.OpenERPSession()
self.session.config = self.config
self.context = self.params.pop('context', None)
self.debug = self.params.pop('debug', False) != False
@ -252,7 +255,30 @@ class HttpRequest(WebRequest):
else:
akw[key] = type(value)
_logger.debug("%s --> %s.%s %r", self.httprequest.method, controller.__class__.__name__, method.__name__, akw)
r = method(controller, self, **self.params)
try:
r = method(controller, self, **self.params)
except xmlrpclib.Fault, e:
r = werkzeug.exceptions.InternalServerError(cgi.escape(simplejson.dumps({
'code': 200,
'message': "OpenERP Server Error",
'data': {
'type': 'server_exception',
'fault_code': e.faultCode,
'debug': "Server %s\nClient %s" % (
e.faultString, traceback.format_exc())
}
})))
except Exception:
logging.getLogger(__name__ + '.HttpRequest.dispatch').exception(
"An error occurred while handling a json request")
r = werkzeug.exceptions.InternalServerError(cgi.escape(simplejson.dumps({
'code': 300,
'message': "OpenERP WebClient Error",
'data': {
'type': 'client_exception',
'debug': "Client %s" % traceback.format_exc()
}
})))
if self.debug or 1:
if isinstance(r, (werkzeug.wrappers.BaseResponse, werkzeug.exceptions.HTTPException)):
_logger.debug('<-- %s', r)

View File

@ -80,6 +80,13 @@ class OpenERPSession(object):
"""
self.build_connection().check_login(force)
def ensure_valid(self):
if self._uid:
try:
self.assert_valid(True)
except Exception:
self._uid = None
def execute(self, model, func, *l, **d):
self.assert_valid()
model = self.build_connection().get_model(model)

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html style="height: 100%%">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>OpenERP</title>
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
%(css)s
%(js)s
<script type="text/javascript">
$(function() {
var s = new openerp.init(%(modules)s);
var webclient = new s.web.WebClient();
webclient.$element = $(document.body);
webclient.start();
});
</script>
</head>
<body class="openerp" id="oe">
<!-- should add a loading message? -->
</body>
</html>

View File

@ -84,24 +84,9 @@ def concat_files(file_list, reader=None, intersperse=""):
files_concat = intersperse.join(files_content)
return files_concat,files_timestamp
html_template = """<!DOCTYPE html>
<html style="height: 100%%">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>OpenERP</title>
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
%(css)s
%(js)s
<script type="text/javascript">
$(function() {
var s = new openerp.init(%(modules)s);
%(init)s
});
</script>
</head>
<body class="openerp" id="oe"></body>
</html>
"""
html_template = None
with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "main.html")) as html_file:
html_template = html_file.read()
class WebClient(openerpweb.Controller):
_cp_path = "/web/webclient"
@ -207,7 +192,6 @@ class WebClient(openerpweb.Controller):
'js': js,
'css': css,
'modules': simplejson.dumps(self.server_wide_modules(req)),
'init': 'new s.web.WebClient().start();',
}
return r
@ -229,7 +213,7 @@ class WebClient(openerpweb.Controller):
else:
lang_obj = None
if lang.count("_") > 0:
if "_" in lang:
separator = "_"
else:
separator = "@"
@ -240,15 +224,15 @@ class WebClient(openerpweb.Controller):
for addon_name in mods:
transl = {"messages":[]}
transs[addon_name] = transl
addons_path = openerpweb.addons_manifest[addon_name]['addons_path']
for l in langs:
addons_path = openerpweb.addons_manifest[addon_name]['addons_path']
f_name = os.path.join(addons_path, addon_name, "po", l + ".po")
if not os.path.exists(f_name):
continue
try:
with open(f_name) as t_file:
po = babel.messages.pofile.read_po(t_file)
except:
except Exception:
continue
for x in po:
if x.id and x.string:
@ -337,18 +321,13 @@ class Database(openerpweb.Controller):
@openerpweb.httprequest
def backup(self, req, backup_db, backup_pwd, token):
try:
db_dump = base64.b64decode(
req.session.proxy("db").dump(backup_pwd, backup_db))
return req.make_response(db_dump,
[('Content-Type', 'application/octet-stream; charset=binary'),
('Content-Disposition', 'attachment; filename="' + backup_db + '.dump"')],
{'fileToken': int(token)}
)
except xmlrpclib.Fault, e:
if e.faultCode and e.faultCode.split(':')[0] == 'AccessDenied':
return 'Backup Database|' + e.faultCode
return 'Backup Database|Could not generate database backup'
db_dump = base64.b64decode(
req.session.proxy("db").dump(backup_pwd, backup_db))
return req.make_response(db_dump,
[('Content-Type', 'application/octet-stream; charset=binary'),
('Content-Disposition', 'attachment; filename="' + backup_db + '.dump"')],
{'fileToken': int(token)}
)
@openerpweb.httprequest
def restore(self, req, db_file, restore_pwd, new_db):
@ -376,6 +355,7 @@ class Session(openerpweb.Controller):
_cp_path = "/web/session"
def session_info(self, req):
req.session.ensure_valid()
return {
"session_id": req.session_id,
"uid": req.session._uid,
@ -415,7 +395,7 @@ class Session(openerpweb.Controller):
if req.session.model('res.users').change_password(
old_password, new_password):
return {'new_password':new_password}
except:
except Exception:
return {'error': 'Original password incorrect, your password was not changed.', 'title': 'Change Password'}
return {'error': 'Error, password not changed !', 'title': 'Change Password'}
@ -524,7 +504,7 @@ class Session(openerpweb.Controller):
req.httpsession['saved_actions'] = saved_actions
# we don't allow more than 10 stored actions
if len(saved_actions["actions"]) >= 10:
del saved_actions["actions"][min(saved_actions["actions"].keys())]
del saved_actions["actions"][min(saved_actions["actions"])]
key = saved_actions["next"]
saved_actions["actions"][key] = the_action
saved_actions["next"] = key + 1
@ -585,10 +565,8 @@ def clean_action(req, action, do_not_eval=False):
if 'domain' in action:
action['domain'] = parse_domain(action['domain'], req.session)
if 'type' not in action:
action['type'] = 'ir.actions.act_window_close'
if action['type'] == 'ir.actions.act_window':
action_type = action.setdefault('type', 'ir.actions.act_window_close')
if action_type == 'ir.actions.act_window':
return fix_view_modes(action)
return action
@ -707,7 +685,7 @@ class Menu(openerpweb.Controller):
# sort by sequence a tree using parent_id
for menu_item in menu_items:
menu_item.setdefault('children', []).sort(
key=lambda x:x["sequence"])
key=operator.itemgetter('sequence'))
return menu_root
@ -760,7 +738,7 @@ class DataSet(openerpweb.Controller):
# shortcut read if we only want the ids
return {
'ids': ids,
'records': map(lambda id: {'id': id}, paginated_ids)
'records': [{'id': id} for id in paginated_ids]
}
records = Model.read(paginated_ids, fields or False, context)
@ -859,6 +837,36 @@ class DataSet(openerpweb.Controller):
return getattr(req.session.model(model), method)(*args, **kwargs)
@openerpweb.jsonrequest
def onchange(self, req, model, method, args, context_id=None):
""" Support method for handling onchange calls: behaves much like call
with the following differences:
* Does not take a domain_id
* Is aware of the return value's structure, and will parse the domains
if needed in order to return either parsed literal domains (in JSON)
or non-literal domain instances, allowing those domains to be used
from JS
:param req:
:type req: web.common.http.JsonRequest
:param str model: object type on which to call the method
:param str method: name of the onchange handler method
:param list args: arguments to call the onchange handler with
:param int context_id: index of the context object in the list of
arguments
:return: result of the onchange call with all domains parsed
"""
result = self.call_common(req, model, method, args, context_id=context_id)
if 'domain' not in result:
return result
result['domain'] = dict(
(k, parse_domain(v, req.session))
for k, v in result['domain'].iteritems())
return result
@openerpweb.jsonrequest
def call(self, req, model, method, args, domain_id=None, context_id=None):
return self.call_common(req, model, method, args, domain_id, context_id)
@ -1031,7 +1039,7 @@ def parse_domain(domain, session):
:param session: Current OpenERP session
:type session: openerpweb.openerpweb.OpenERPSession
"""
if not isinstance(domain, (str, unicode)):
if not isinstance(domain, basestring):
return domain
try:
return ast.literal_eval(domain)
@ -1048,7 +1056,7 @@ def parse_context(context, session):
:param session: Current OpenERP session
:type session: openerpweb.openerpweb.OpenERPSession
"""
if not isinstance(context, (str, unicode)):
if not isinstance(context, basestring):
return context
try:
return ast.literal_eval(context)
@ -1516,7 +1524,7 @@ class CSVExport(Export):
d = d.replace('\n',' ').replace('\t',' ')
try:
d = d.encode('utf-8')
except:
except UnicodeError:
pass
if d is False: d = None
row.append(d)

View File

@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-12-20 18:48+0100\n"
"PO-Revision-Date: 2012-01-12 05:44+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@gmail.com>\n"
"PO-Revision-Date: 2012-01-19 13:35+0000\n"
"Last-Translator: Jeff Wang <wjfonhand@hotmail.com>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-01-13 05:01+0000\n"
"X-Generator: Launchpad (build 14664)\n"
"X-Launchpad-Export-Date: 2012-01-20 05:05+0000\n"
"X-Generator: Launchpad (build 14700)\n"
#: addons/web/static/src/js/chrome.js:162
#: addons/web/static/src/js/chrome.js:175
@ -107,12 +107,12 @@ msgstr "无效的搜索"
#: addons/web/static/src/js/search.js:403
msgid "triggered from search view"
msgstr ""
msgstr "在搜索视图进入"
#: addons/web/static/src/js/search.js:490
#, python-format
msgid "Incorrect value for field %(fieldname)s: [%(value)s] is %(message)s"
msgstr ""
msgstr "字段值有误。%(fieldname)s: [%(value)s] : %(message)s"
#: addons/web/static/src/js/search.js:822
msgid "not a valid integer"
@ -205,7 +205,7 @@ msgstr "为假"
#: addons/web/static/src/js/view_editor.js:42
msgid "ViewEditor"
msgstr ""
msgstr "界面设计器"
#: addons/web/static/src/js/view_editor.js:46
#: addons/web/static/src/js/view_list.js:17
@ -414,7 +414,7 @@ msgstr "#{text}"
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr ""
msgstr "自豪地使用"
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
@ -617,7 +617,7 @@ msgstr "调试视图#"
#: addons/web/static/src/xml/base.xml:0
msgid "- Fields View Get"
msgstr ""
msgstr "界面源代码"
#: addons/web/static/src/xml/base.xml:0
msgid "- Edit"
@ -673,7 +673,7 @@ msgstr "“"
#: addons/web/static/src/xml/base.xml:0
msgid "Modifiers:"
msgstr ""
msgstr "属性"
#: addons/web/static/src/xml/base.xml:0
msgid "?"
@ -681,7 +681,7 @@ msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "(nolabel)"
msgstr ""
msgstr "无标签"
#: addons/web/static/src/xml/base.xml:0
msgid "Field:"
@ -713,7 +713,7 @@ msgstr "域:"
#: addons/web/static/src/xml/base.xml:0
msgid "On change:"
msgstr ""
msgstr "变更时动作:"
#: addons/web/static/src/xml/base.xml:0
msgid "Relation:"
@ -721,7 +721,7 @@ msgstr "关系:"
#: addons/web/static/src/xml/base.xml:0
msgid "Selection:"
msgstr ""
msgstr "下拉列表:"
#: addons/web/static/src/xml/base.xml:0
msgid "["
@ -777,11 +777,11 @@ msgstr "按钮"
#: addons/web/static/src/xml/base.xml:0
msgid "(no string)"
msgstr ""
msgstr "无字符串"
#: addons/web/static/src/xml/base.xml:0
msgid "Special:"
msgstr ""
msgstr "特殊:"
#: addons/web/static/src/xml/base.xml:0
msgid "Button Type:"
@ -875,7 +875,7 @@ msgstr "导出类型:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr ""
msgstr "用可导入的格式导出"
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
@ -938,6 +938,8 @@ msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
"选择要导入的CSV文件。如果需要导入文件的模版\n"
"可以用导出工具并选中 “导入兼容”"
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
@ -1032,6 +1034,10 @@ msgid ""
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
"是个自由的企业级软件系统,通过信息集成提升企业\n"
"生产力和盈利能力。它连接、改进和管控企业流程的\n"
"方方面面。包括销售、财务、供应链、项目管理、生\n"
"产、服务和客户关系管理等"
#: addons/web/static/src/xml/base.xml:0
msgid ""
@ -1044,6 +1050,9 @@ msgid ""
" production system and migration to a new version to be "
"straightforward."
msgstr ""
"该系统是跨平台的可以安装在Windows、Mac OSX\n"
"和各种Linux或类UNIX发行版上。 它的架构支持\n"
"快速开发新功能、修改现有功能或直接升级到新版本"
#: addons/web/static/src/xml/base.xml:0
msgid ""

View File

@ -171,6 +171,7 @@ body { padding: 0; margin: 0; }
padding: 5px 10px;
color: #eee;
border: solid 1px #333;
background: #1e1e1e;
background: rgba(30,30,30,0.94);
-moz-border-radius: 0 0 8px 8px;
-webkit-border-radius: 0 0 8px 8px;
@ -197,6 +198,7 @@ body { padding: 0; margin: 0; }
left: 50%;
margin: -160px -166px;
border: solid 1px #333333;
background: #1e1e1e;
background: rgba(30,30,30,0.94);
padding: 22px 32px;
text-align: left;

View File

@ -472,16 +472,13 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
self.blockUI();
self.session.get_file({
form: form,
error: function (body) {
var error = body.firstChild.data.split('|');
self.display_error({
title: error[0],
error: error[1]
});
success: function () {
self.do_notify(_t("Backed"),
_t("Database backed up successfully"));
},
error: openerp.webclient.crashmanager.on_rpc_error,
complete: function() {
self.unblockUI();
self.do_notify(_t("Backed"), _t("Database backed up successfully"));
}
});
}
@ -1064,7 +1061,6 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
},
start: function() {
var self = this;
this.$element = $(document.body);
if (jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) {
this.$element.addClass("kitten-mode-activated");
this.$element.delegate('img.oe-record-edit-link-img', 'hover', function(e) {

View File

@ -809,8 +809,15 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
.attr({id: id, name: id})
.appendTo(document.body)
.load(function () {
if (options.error) { options.error(this.contentDocument.body); }
complete();
try {
if (options.error) {
options.error(JSON.parse(
this.contentDocument.body.childNodes[1].textContent
));
}
} finally {
complete();
}
});
if (options.form) {

View File

@ -316,7 +316,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
var change_spec = self.parse_on_change(on_change, widget);
if (change_spec) {
var ajax = {
url: '/web/dataset/call',
url: '/web/dataset/onchange',
async: false
};
return self.rpc(ajax, {
@ -342,6 +342,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
var result = response;
if (result.value) {
for (var f in result.value) {
if (!result.value.hasOwnProperty(f)) { continue; }
var field = this.fields[f];
// If field is not defined in the view, just ignore it
if (field) {
@ -367,7 +368,14 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
});
}
if (result.domain) {
// TODO:
function edit_domain(node) {
var new_domain = result.domain[node.attrs.name];
if (new_domain) {
node.attrs.domain = new_domain;
}
_(node.children).each(edit_domain);
}
edit_domain(this.fields_view.arch);
}
return $.Deferred().resolve();
} catch(e) {
@ -537,6 +545,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
get_fields_values: function(blacklist) {
blacklist = blacklist || [];
var values = {};
var ids = this.get_selected_ids();
values["id"] = ids.length > 0 ? ids[0] : false;
_.each(this.fields, function(value, key) {
if (_.include(blacklist, key))
return;
@ -790,7 +800,7 @@ openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form.
return QWeb.render(template, { "widget": this });
},
do_attach_tooltip: function(widget, trigger, options) {
if ($.browser.mozilla && parseInt($.browser.version.split('.')[0], 10) < 2) {
if ($.browser.mozilla) {
// Unknown bug in old version of firefox :
// input type=text onchange event not fired when tootip is shown
return;

View File

@ -195,7 +195,8 @@ session.web.ActionManager = session.web.Widget.extend({
on_closed();
}
self.dialog_stop();
}
},
error: session.webclient.crashmanager.on_rpc_error
})
});
},
@ -310,11 +311,15 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View
this.views[view_type].deferred.resolve(view_type);
$.when(view_promise).then(function() {
self.on_controller_inited(view_type, controller);
if (self.searchview && view.controller.searchable !== false) {
if (self.searchview
&& self.flags.auto_search !== false
&& view.controller.searchable !== false) {
self.searchview.ready.then(self.searchview.do_search);
}
});
} else if (this.searchview && view.controller.searchable !== false) {
} else if (this.searchview
&& self.flags.auto_search !== false
&& view.controller.searchable !== false) {
this.searchview.ready.then(this.searchview.do_search);
}
@ -448,6 +453,7 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner
// do not have it yet (and we don't, because we've not called our own
// ``_super()``) rpc requests will blow up.
var flags = action.flags || {};
flags.auto_search = !!action.auto_search;
if (action.res_model == 'board.board' && action.view_mode === 'form') {
// Special case for Dashboards
_.extend(flags, {

View File

@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-12-20 18:48+0100\n"
"PO-Revision-Date: 2012-01-12 05:35+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@gmail.com>\n"
"PO-Revision-Date: 2012-01-19 13:40+0000\n"
"Last-Translator: Jeff Wang <wjfonhand@hotmail.com>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-01-13 05:01+0000\n"
"X-Generator: Launchpad (build 14664)\n"
"X-Launchpad-Export-Date: 2012-01-20 05:05+0000\n"
"X-Generator: Launchpad (build 14700)\n"
#: addons/web_dashboard/static/src/js/dashboard.js:63
msgid "Edit Layout"
@ -53,7 +53,7 @@ msgstr "%"
msgid ""
"Click on the functionalites listed below to launch them and configure your "
"system"
msgstr ""
msgstr "单击以下功能列表打开配置界面"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Welcome to OpenERP"

View File

@ -8,18 +8,18 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-12-20 18:48+0100\n"
"PO-Revision-Date: 2012-01-12 05:36+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@gmail.com>\n"
"PO-Revision-Date: 2012-01-19 13:42+0000\n"
"Last-Translator: Jeff Wang <wjfonhand@hotmail.com>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-01-13 05:01+0000\n"
"X-Generator: Launchpad (build 14664)\n"
"X-Launchpad-Export-Date: 2012-01-20 05:05+0000\n"
"X-Generator: Launchpad (build 14700)\n"
#: addons/web_diagram/static/src/js/diagram.js:11
msgid "Diagram"
msgstr ""
msgstr "图表"
#: addons/web_diagram/static/src/js/diagram.js:210
msgid "Cancel"

View File

@ -8,15 +8,15 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-12-20 18:48+0100\n"
"PO-Revision-Date: 2012-01-07 05:43+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"PO-Revision-Date: 2012-01-19 13:43+0000\n"
"Last-Translator: hifly <Unknown>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-01-08 05:27+0000\n"
"X-Generator: Launchpad (build 14640)\n"
"X-Launchpad-Export-Date: 2012-01-20 05:05+0000\n"
"X-Generator: Launchpad (build 14700)\n"
#: addons/web_graph/static/src/js/graph.js:19
msgid "Graph"
msgstr ""
msgstr "图形"