[MERGE] from trunk
bzr revid: xmo@openerp.com-20110822123258-thxewwdvbysap4jt
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
'active': True,
|
||||
'js' : [
|
||||
"static/lib/datejs/date-en-US.js",
|
||||
"static/lib/datejs/strftime.js",
|
||||
"static/lib/jquery/jquery-1.6.2.js",
|
||||
"static/lib/jquery.form/jquery.form.js",
|
||||
"static/lib/jquery.validate/jquery.validate.js",
|
||||
@@ -22,6 +23,7 @@
|
||||
"static/lib/underscore/underscore.string.js",
|
||||
"static/src/js/boot.js",
|
||||
"static/src/js/core.js",
|
||||
"static/src/js/dates.js",
|
||||
"static/src/js/formats.js",
|
||||
"static/src/js/chrome.js",
|
||||
"static/src/js/views.js",
|
||||
|
||||
@@ -67,7 +67,6 @@ def manifest_glob(addons, key):
|
||||
files = []
|
||||
for addon in addons:
|
||||
globlist = openerpweb.addons_manifest.get(addon, {}).get(key, [])
|
||||
print globlist
|
||||
for pattern in globlist:
|
||||
for path in glob.glob(os.path.join(openerpweb.path_addons, addon, pattern)):
|
||||
files.append(path[len(openerpweb.path_addons):])
|
||||
@@ -79,35 +78,36 @@ def concat_files(file_list):
|
||||
concat: concatenation of file content
|
||||
timestamp: max(os.path.getmtime of file_list)
|
||||
"""
|
||||
root = openerpweb.path_root
|
||||
files_content = []
|
||||
files_timestamp = 0
|
||||
for i in file_list:
|
||||
fname = os.path.join(root, i)
|
||||
fname = os.path.join(openerpweb.path_addons, i[1:])
|
||||
ftime = os.path.getmtime(fname)
|
||||
if ftime > files_timestamp:
|
||||
files_timestamp = ftime
|
||||
files_content = open(fname).read()
|
||||
files_content.append(open(fname).read())
|
||||
files_concat = "".join(files_content)
|
||||
return files_concat
|
||||
return (files_concat,files_timestamp)
|
||||
|
||||
home_template = textwrap.dedent("""<!DOCTYPE html>
|
||||
<html style="height: 100%%">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>OpenERP</title>
|
||||
%(javascript)s
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
QWeb = new QWeb2.Engine();
|
||||
openerp.init().base.webclient("oe");
|
||||
});
|
||||
</script>
|
||||
<link rel="shortcut icon" href="/base/static/src/img/favicon.ico" type="image/x-icon"/>
|
||||
%(css)s
|
||||
<!--[if lte IE 7]>
|
||||
<link rel="stylesheet" href="/base/static/src/css/base-ie7.css" type="text/css"/>
|
||||
<![endif]-->
|
||||
%(javascript)s
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
QWeb = new QWeb2.Engine();
|
||||
var c = new openerp.init();
|
||||
var wc = new c.base.WebClient("oe");
|
||||
wc.start();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body id="oe" class="openerp"></body>
|
||||
</html>
|
||||
@@ -125,31 +125,31 @@ class WebClient(openerpweb.Controller):
|
||||
|
||||
@openerpweb.httprequest
|
||||
def css(self, req, mods='base'):
|
||||
cherrypy.response.headers['Content-Type'] = 'text/css'
|
||||
req.httpresponse.headers['Content-Type'] = 'text/css'
|
||||
files = manifest_glob(mods.split(','), 'css')
|
||||
concat = concat_files(files)[0]
|
||||
content,timestamp = concat_files(files)
|
||||
# TODO request set the Date of last modif and Etag
|
||||
return concat
|
||||
return content
|
||||
|
||||
@openerpweb.httprequest
|
||||
def js(self, req, mods='base'):
|
||||
cherrypy.response.headers['Content-Type'] = 'application/javascript'
|
||||
req.httpresponse.headers['Content-Type'] = 'application/javascript'
|
||||
files = manifest_glob(mods.split(','), 'js')
|
||||
concat = concat_files(files)[0]
|
||||
content,timestamp = concat_files(files)
|
||||
# TODO request set the Date of last modif and Etag
|
||||
return concat
|
||||
return content
|
||||
|
||||
@openerpweb.httprequest
|
||||
def home(self, req, s_action=None):
|
||||
# script tags
|
||||
jslist = ['/base/webclient/js']
|
||||
if 1: # debug == 1
|
||||
if req.debug:
|
||||
jslist = manifest_glob(['base'], 'js')
|
||||
js = "\n ".join(['<script type="text/javascript" src="%s"></script>'%i for i in jslist])
|
||||
|
||||
# css tags
|
||||
csslist = ['/base/webclient/css']
|
||||
if 1: # debug == 1
|
||||
if req.debug:
|
||||
csslist = manifest_glob(['base'], 'css')
|
||||
css = "\n ".join(['<link rel="stylesheet" href="%s">'%i for i in csslist])
|
||||
r = home_template % {
|
||||
@@ -157,7 +157,7 @@ class WebClient(openerpweb.Controller):
|
||||
'css': css
|
||||
}
|
||||
return r
|
||||
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def translations(self, req, mods, lang):
|
||||
lang_model = req.session.model('res.lang')
|
||||
@@ -193,7 +193,6 @@ class WebClient(openerpweb.Controller):
|
||||
transl["messages"].append({'id': x.id, 'string': x.string})
|
||||
return {"modules": transs,
|
||||
"lang_parameters": lang_obj}
|
||||
|
||||
|
||||
class Database(openerpweb.Controller):
|
||||
_cp_path = "/base/database"
|
||||
@@ -249,16 +248,16 @@ class Database(openerpweb.Controller):
|
||||
try:
|
||||
db_dump = base64.decodestring(
|
||||
req.session.proxy("db").dump(backup_pwd, backup_db))
|
||||
cherrypy.response.headers['Content-Type'] = "application/octet-stream; charset=binary"
|
||||
cherrypy.response.headers['Content-Disposition'] = 'attachment; filename="' + backup_db + '.dump"'
|
||||
cherrypy.response.cookie['fileToken'] = token
|
||||
cherrypy.response.cookie['fileToken']['path'] = '/'
|
||||
req.httpresponse.headers['Content-Type'] = "application/octet-stream; charset=binary"
|
||||
req.httpresponse.headers['Content-Disposition'] = 'attachment; filename="' + backup_db + '.dump"'
|
||||
req.httpresponse.cookie['fileToken'] = token
|
||||
req.httpresponse.cookie['fileToken']['path'] = '/'
|
||||
return db_dump
|
||||
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'
|
||||
|
||||
|
||||
@openerpweb.httprequest
|
||||
def restore(self, req, db_file, restore_pwd, new_db):
|
||||
try:
|
||||
@@ -267,9 +266,7 @@ class Database(openerpweb.Controller):
|
||||
return ''
|
||||
except xmlrpclib.Fault, e:
|
||||
if e.faultCode and e.faultCode.split(':')[0] == 'AccessDenied':
|
||||
raise cherrypy.HTTPError(403)
|
||||
|
||||
raise cherrypy.HTTPError()
|
||||
raise Exception("AccessDenied")
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def change_password(self, req, fields):
|
||||
@@ -386,10 +383,10 @@ class Session(openerpweb.Controller):
|
||||
:return: A key identifying the saved action.
|
||||
:rtype: integer
|
||||
"""
|
||||
saved_actions = cherrypy.session.get('saved_actions')
|
||||
saved_actions = req.httpsession.get('saved_actions')
|
||||
if not saved_actions:
|
||||
saved_actions = {"next":0, "actions":{}}
|
||||
cherrypy.session['saved_actions'] = saved_actions
|
||||
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())]
|
||||
@@ -409,7 +406,7 @@ class Session(openerpweb.Controller):
|
||||
:return: The saved action or None.
|
||||
:rtype: anything
|
||||
"""
|
||||
saved_actions = cherrypy.session.get('saved_actions')
|
||||
saved_actions = req.httpsession.get('saved_actions')
|
||||
if not saved_actions:
|
||||
return None
|
||||
return saved_actions["actions"].get(key)
|
||||
@@ -439,18 +436,16 @@ def clean_action(action, session, context=None):
|
||||
return action
|
||||
# values come from the server, we can just eval them
|
||||
if isinstance(action.get('context'), basestring):
|
||||
action['context'] = eval(
|
||||
action['context'],
|
||||
session.evaluation_context(context=context)) or {}
|
||||
localvars = session.evaluation_context(context=context)
|
||||
action['context'] = eval( action['context'], localvars ) or {}
|
||||
|
||||
if isinstance(action.get('domain'), basestring):
|
||||
action['domain'] = eval(
|
||||
action['domain'],
|
||||
session.evaluation_context(
|
||||
action.get('context', {}))) or []
|
||||
localvars = session.evaluation_context( action.get('context', {}))
|
||||
action['domain'] = eval( action['domain'], localvars ) or []
|
||||
|
||||
return fix_view_modes(action)
|
||||
|
||||
# I think generate_views,fix_view_modes should go into js ActionManager
|
||||
def generate_views(action):
|
||||
"""
|
||||
While the server generates a sequence called "views" computing dependencies
|
||||
@@ -947,10 +942,10 @@ class Binary(openerpweb.Controller):
|
||||
_cp_path = "/base/binary"
|
||||
|
||||
@openerpweb.httprequest
|
||||
def image(self, request, session_id, model, id, field, **kw):
|
||||
cherrypy.response.headers['Content-Type'] = 'image/png'
|
||||
Model = request.session.model(model)
|
||||
context = request.session.eval_context(request.context)
|
||||
def image(self, req, model, id, field, **kw):
|
||||
req.httpresponse.headers['Content-Type'] = 'image/png'
|
||||
Model = req.session.model(model)
|
||||
context = req.session.eval_context(req.context)
|
||||
try:
|
||||
if not id:
|
||||
res = Model.default_get([field], context).get(field, '')
|
||||
@@ -963,26 +958,26 @@ class Binary(openerpweb.Controller):
|
||||
return open(os.path.join(openerpweb.path_addons, 'base', 'static', 'src', 'img', 'placeholder.png'), 'rb').read()
|
||||
|
||||
@openerpweb.httprequest
|
||||
def saveas(self, request, session_id, model, id, field, fieldname, **kw):
|
||||
Model = request.session.model(model)
|
||||
context = request.session.eval_context(request.context)
|
||||
def saveas(self, req, model, id, field, fieldname, **kw):
|
||||
Model = req.session.model(model)
|
||||
context = req.session.eval_context(req.context)
|
||||
res = Model.read([int(id)], [field, fieldname], context)[0]
|
||||
filecontent = res.get(field, '')
|
||||
if not filecontent:
|
||||
raise cherrypy.NotFound
|
||||
else:
|
||||
cherrypy.response.headers['Content-Type'] = 'application/octet-stream'
|
||||
req.httpresponse.headers['Content-Type'] = 'application/octet-stream'
|
||||
filename = '%s_%s' % (model.replace('.', '_'), id)
|
||||
if fieldname:
|
||||
filename = res.get(fieldname, '') or filename
|
||||
cherrypy.response.headers['Content-Disposition'] = 'attachment; filename=' + filename
|
||||
req.httpresponse.headers['Content-Disposition'] = 'attachment; filename=' + filename
|
||||
return base64.decodestring(filecontent)
|
||||
|
||||
@openerpweb.httprequest
|
||||
def upload(self, request, session_id, callback, ufile=None):
|
||||
def upload(self, req, callback, ufile=None):
|
||||
cherrypy.response.timeout = 500
|
||||
headers = {}
|
||||
for key, val in cherrypy.request.headers.iteritems():
|
||||
for key, val in req.httprequest.headers.iteritems():
|
||||
headers[key.lower()] = val
|
||||
size = int(headers.get('content-length', 0))
|
||||
# TODO: might be useful to have a configuration flag for max-length file uploads
|
||||
@@ -1006,10 +1001,10 @@ class Binary(openerpweb.Controller):
|
||||
return out % (simplejson.dumps(callback), simplejson.dumps(args))
|
||||
|
||||
@openerpweb.httprequest
|
||||
def upload_attachment(self, request, session_id, callback, model, id, ufile=None):
|
||||
def upload_attachment(self, req, callback, model, id, ufile=None):
|
||||
cherrypy.response.timeout = 500
|
||||
context = request.session.eval_context(request.context)
|
||||
Model = request.session.model('ir.attachment')
|
||||
context = req.session.eval_context(req.context)
|
||||
Model = req.session.model('ir.attachment')
|
||||
try:
|
||||
out = """<script language="javascript" type="text/javascript">
|
||||
var win = window.top.window,
|
||||
|
||||
+451
-1
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"POT-Creation-Date: 2011-08-17 13:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -30,3 +30,453 @@ msgstr ""
|
||||
msgid "<em> Create and Edit...</em>"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "x"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "#{title}"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "#{text}"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Powered by"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "openerp.com"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Loading..."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Create"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Drop"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Backup"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Restore"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Back to Login"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "CREATE DATABASE"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Master password:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "New database name:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Load Demonstration data:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Default language:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Admin password:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Confirm password:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "DROP DATABASE"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Database:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Master Password:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "BACKUP DATABASE"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "RESTORE DATABASE"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "File:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "CHANGE MASTER PASSWORD"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "New master password:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Confirm new master password:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "User:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Password:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Database"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Bad username or password"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid ""
|
||||
"We think that daily job activities can be more intuitive, efficient, "
|
||||
"automated, .. and even fun."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "OpenERP's vision to be:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Full featured"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid ""
|
||||
"Today's enterprise challenges are multiple. We provide one module for "
|
||||
"each need."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Open Source"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid ""
|
||||
"To Build a great product, we rely on the knowledge of thousands of "
|
||||
"contributors."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "User Friendly"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "In order to be productive, people need clean and easy to use interface."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "-"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "rpc_session_id:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "1"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "LOGOUT"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "h3"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "<"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid ">"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "</"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "h4"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "First"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Last"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "♻"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "xml"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Save & Edit"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Create & Edit"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "<<"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "0"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "/"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid ">>"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Unhandled widget"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "?"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid ":"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Open..."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Create..."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Search..."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "One2Many widget"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Uploading ..."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Save As"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Advanced Filter"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "-- Filters --"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "-- Actions --"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Save Filter"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Manage Filters"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Filter Name:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "(Any existing filter with the same name will be replaced)"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "(?)"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Any of the following conditions must match"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "All the following conditions must match"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "None of the following conditions must match"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Add condition"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "and"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Save & New"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Save & Close"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid ""
|
||||
"This wizard will export all data that matches the current search criteria"
|
||||
" to a CSV file.\n"
|
||||
" You can export all data or only the fields that can be "
|
||||
"reimported after modification."
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Export Type:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Import Compatible Export"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Export all Data"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Export Format"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "CSV"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Excel"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Available fields"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Fields to export"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Save fields list"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Remove"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Remove All"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid " "
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Save as:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Ok"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base/static/src/xml/base.xml:0
|
||||
msgid "Saved exports:"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -0,0 +1,731 @@
|
||||
/*
|
||||
strftime for Javascript
|
||||
Copyright (c) 2008, Philip S Tellis <philip@bluesmoon.info>
|
||||
All rights reserved.
|
||||
|
||||
This code is distributed under the terms of the BSD licence
|
||||
|
||||
Redistribution and use of this software in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
||||
and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* The names of the contributors to this file may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file strftime.js
|
||||
* \author Philip S Tellis \<philip@bluesmoon.info\>
|
||||
* \version 1.3
|
||||
* \date 2008/06
|
||||
* \brief Javascript implementation of strftime
|
||||
*
|
||||
* Implements strftime for the Date object in javascript based on the PHP implementation described at
|
||||
* http://www.php.net/strftime This is in turn based on the Open Group specification defined
|
||||
* at http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html This implementation does not
|
||||
* include modified conversion specifiers (i.e., Ex and Ox)
|
||||
*
|
||||
* The following format specifiers are supported:
|
||||
*
|
||||
* \copydoc formats
|
||||
*
|
||||
* \%a, \%A, \%b and \%B should be localised for non-English locales.
|
||||
*
|
||||
* \par Usage:
|
||||
* This library may be used as follows:
|
||||
* \code
|
||||
* var d = new Date();
|
||||
*
|
||||
* var ymd = d.strftime('%Y/%m/%d');
|
||||
* var iso = d.strftime('%Y-%m-%dT%H:%M:%S%z');
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* \sa \link Date.prototype.strftime Date.strftime \endlink for a description of each of the supported format specifiers
|
||||
* \sa Date.ext.locales for localisation information
|
||||
* \sa http://www.php.net/strftime for the PHP implementation which is the basis for this
|
||||
* \sa http://tech.bluesmoon.info/2008/04/strftime-in-javascript.html for feedback
|
||||
*/
|
||||
|
||||
//! Date extension object - all supporting objects go in here.
|
||||
Date.ext = {};
|
||||
|
||||
//! Utility methods
|
||||
Date.ext.util = {};
|
||||
|
||||
/**
|
||||
\brief Left pad a number with something
|
||||
\details Takes a number and pads it to the left with the passed in pad character
|
||||
\param x The number to pad
|
||||
\param pad The string to pad with
|
||||
\param r [optional] Upper limit for pad. A value of 10 pads to 2 digits, a value of 100 pads to 3 digits.
|
||||
Default is 10.
|
||||
|
||||
\return The number left padded with the pad character. This function returns a string and not a number.
|
||||
*/
|
||||
Date.ext.util.xPad=function(x, pad, r)
|
||||
{
|
||||
if(typeof(r) == 'undefined')
|
||||
{
|
||||
r=10;
|
||||
}
|
||||
for( ; parseInt(x, 10)<r && r>1; r/=10)
|
||||
x = pad.toString() + x;
|
||||
return x.toString();
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Currently selected locale.
|
||||
\details
|
||||
The locale for a specific date object may be changed using \code Date.locale = "new-locale"; \endcode
|
||||
The default will be based on the lang attribute of the HTML tag of your document
|
||||
*/
|
||||
Date.prototype.locale = 'en-GB';
|
||||
//! \cond FALSE
|
||||
if(document.getElementsByTagName('html') && document.getElementsByTagName('html')[0].lang)
|
||||
{
|
||||
Date.prototype.locale = document.getElementsByTagName('html')[0].lang;
|
||||
}
|
||||
//! \endcond
|
||||
|
||||
/**
|
||||
\brief Localised strings for days of the week and months of the year.
|
||||
\details
|
||||
To create your own local strings, add a locale object to the locales object.
|
||||
The key of your object should be the same as your locale name. For example:
|
||||
en-US,
|
||||
fr,
|
||||
fr-CH,
|
||||
de-DE
|
||||
Names are case sensitive and are described at http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
|
||||
Your locale object must contain the following keys:
|
||||
\param a Short names of days of week starting with Sunday
|
||||
\param A Long names days of week starting with Sunday
|
||||
\param b Short names of months of the year starting with January
|
||||
\param B Long names of months of the year starting with February
|
||||
\param c The preferred date and time representation in your locale
|
||||
\param p AM or PM in your locale
|
||||
\param P am or pm in your locale
|
||||
\param x The preferred date representation for the current locale without the time.
|
||||
\param X The preferred time representation for the current locale without the date.
|
||||
|
||||
\sa Date.ext.locales.en for a sample implementation
|
||||
\sa \ref localisation for detailed documentation on localising strftime for your own locale
|
||||
*/
|
||||
Date.ext.locales = { };
|
||||
|
||||
/**
|
||||
* \brief Localised strings for English (British).
|
||||
* \details
|
||||
* This will be used for any of the English dialects unless overridden by a country specific one.
|
||||
* This is the default locale if none specified
|
||||
*/
|
||||
Date.ext.locales.en = {
|
||||
a: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
||||
A: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
||||
b: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
||||
B: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
||||
c: '%a %d %b %Y %T %Z',
|
||||
p: ['AM', 'PM'],
|
||||
P: ['am', 'pm'],
|
||||
x: '%d/%m/%y',
|
||||
X: '%T'
|
||||
};
|
||||
|
||||
//! \cond FALSE
|
||||
// Localised strings for US English
|
||||
Date.ext.locales['en-US'] = Date.ext.locales.en;
|
||||
Date.ext.locales['en-US'].c = '%a %d %b %Y %r %Z';
|
||||
Date.ext.locales['en-US'].x = '%D';
|
||||
Date.ext.locales['en-US'].X = '%r';
|
||||
|
||||
// Localised strings for British English
|
||||
Date.ext.locales['en-GB'] = Date.ext.locales.en;
|
||||
|
||||
// Localised strings for Australian English
|
||||
Date.ext.locales['en-AU'] = Date.ext.locales['en-GB'];
|
||||
//! \endcond
|
||||
|
||||
//! \brief List of supported format specifiers.
|
||||
/**
|
||||
* \details
|
||||
* \arg \%a - abbreviated weekday name according to the current locale
|
||||
* \arg \%A - full weekday name according to the current locale
|
||||
* \arg \%b - abbreviated month name according to the current locale
|
||||
* \arg \%B - full month name according to the current locale
|
||||
* \arg \%c - preferred date and time representation for the current locale
|
||||
* \arg \%C - century number (the year divided by 100 and truncated to an integer, range 00 to 99)
|
||||
* \arg \%d - day of the month as a decimal number (range 01 to 31)
|
||||
* \arg \%D - same as %m/%d/%y
|
||||
* \arg \%e - day of the month as a decimal number, a single digit is preceded by a space (range ' 1' to '31')
|
||||
* \arg \%g - like %G, but without the century
|
||||
* \arg \%G - The 4-digit year corresponding to the ISO week number
|
||||
* \arg \%h - same as %b
|
||||
* \arg \%H - hour as a decimal number using a 24-hour clock (range 00 to 23)
|
||||
* \arg \%I - hour as a decimal number using a 12-hour clock (range 01 to 12)
|
||||
* \arg \%j - day of the year as a decimal number (range 001 to 366)
|
||||
* \arg \%m - month as a decimal number (range 01 to 12)
|
||||
* \arg \%M - minute as a decimal number
|
||||
* \arg \%n - newline character
|
||||
* \arg \%p - either `AM' or `PM' according to the given time value, or the corresponding strings for the current locale
|
||||
* \arg \%P - like %p, but lower case
|
||||
* \arg \%r - time in a.m. and p.m. notation equal to %I:%M:%S %p
|
||||
* \arg \%R - time in 24 hour notation equal to %H:%M
|
||||
* \arg \%S - second as a decimal number
|
||||
* \arg \%t - tab character
|
||||
* \arg \%T - current time, equal to %H:%M:%S
|
||||
* \arg \%u - weekday as a decimal number [1,7], with 1 representing Monday
|
||||
* \arg \%U - week number of the current year as a decimal number, starting with
|
||||
* the first Sunday as the first day of the first week
|
||||
* \arg \%V - The ISO 8601:1988 week number of the current year as a decimal number,
|
||||
* range 01 to 53, where week 1 is the first week that has at least 4 days
|
||||
* in the current year, and with Monday as the first day of the week.
|
||||
* \arg \%w - day of the week as a decimal, Sunday being 0
|
||||
* \arg \%W - week number of the current year as a decimal number, starting with the
|
||||
* first Monday as the first day of the first week
|
||||
* \arg \%x - preferred date representation for the current locale without the time
|
||||
* \arg \%X - preferred time representation for the current locale without the date
|
||||
* \arg \%y - year as a decimal number without a century (range 00 to 99)
|
||||
* \arg \%Y - year as a decimal number including the century
|
||||
* \arg \%z - numerical time zone representation
|
||||
* \arg \%Z - time zone name or abbreviation
|
||||
* \arg \%% - a literal `\%' character
|
||||
*/
|
||||
Date.ext.formats = {
|
||||
a: function(d) { return Date.ext.locales[d.locale].a[d.getDay()]; },
|
||||
A: function(d) { return Date.ext.locales[d.locale].A[d.getDay()]; },
|
||||
b: function(d) { return Date.ext.locales[d.locale].b[d.getMonth()]; },
|
||||
B: function(d) { return Date.ext.locales[d.locale].B[d.getMonth()]; },
|
||||
c: 'toLocaleString',
|
||||
C: function(d) { return Date.ext.util.xPad(parseInt(d.getFullYear()/100, 10), 0); },
|
||||
d: ['getDate', '0'],
|
||||
e: ['getDate', ' '],
|
||||
g: function(d) { return Date.ext.util.xPad(parseInt(Date.ext.util.G(d)/100, 10), 0); },
|
||||
G: function(d) {
|
||||
var y = d.getFullYear();
|
||||
var V = parseInt(Date.ext.formats.V(d), 10);
|
||||
var W = parseInt(Date.ext.formats.W(d), 10);
|
||||
|
||||
if(W > V) {
|
||||
y++;
|
||||
} else if(W===0 && V>=52) {
|
||||
y--;
|
||||
}
|
||||
|
||||
return y;
|
||||
},
|
||||
H: ['getHours', '0'],
|
||||
I: function(d) { var I=d.getHours()%12; return Date.ext.util.xPad(I===0?12:I, 0); },
|
||||
j: function(d) {
|
||||
var ms = d - new Date('' + d.getFullYear() + '/1/1 GMT');
|
||||
ms += d.getTimezoneOffset()*60000;
|
||||
var doy = parseInt(ms/60000/60/24, 10)+1;
|
||||
return Date.ext.util.xPad(doy, 0, 100);
|
||||
},
|
||||
m: function(d) { return Date.ext.util.xPad(d.getMonth()+1, 0); },
|
||||
M: ['getMinutes', '0'],
|
||||
p: function(d) { return Date.ext.locales[d.locale].p[d.getHours() >= 12 ? 1 : 0 ]; },
|
||||
P: function(d) { return Date.ext.locales[d.locale].P[d.getHours() >= 12 ? 1 : 0 ]; },
|
||||
S: ['getSeconds', '0'],
|
||||
u: function(d) { var dow = d.getDay(); return dow===0?7:dow; },
|
||||
U: function(d) {
|
||||
var doy = parseInt(Date.ext.formats.j(d), 10);
|
||||
var rdow = 6-d.getDay();
|
||||
var woy = parseInt((doy+rdow)/7, 10);
|
||||
return Date.ext.util.xPad(woy, 0);
|
||||
},
|
||||
V: function(d) {
|
||||
var woy = parseInt(Date.ext.formats.W(d), 10);
|
||||
var dow1_1 = (new Date('' + d.getFullYear() + '/1/1')).getDay();
|
||||
// First week is 01 and not 00 as in the case of %U and %W,
|
||||
// so we add 1 to the final result except if day 1 of the year
|
||||
// is a Monday (then %W returns 01).
|
||||
// We also need to subtract 1 if the day 1 of the year is
|
||||
// Friday-Sunday, so the resulting equation becomes:
|
||||
var idow = woy + (dow1_1 > 4 || dow1_1 <= 1 ? 0 : 1);
|
||||
if(idow == 53 && (new Date('' + d.getFullYear() + '/12/31')).getDay() < 4)
|
||||
{
|
||||
idow = 1;
|
||||
}
|
||||
else if(idow === 0)
|
||||
{
|
||||
idow = Date.ext.formats.V(new Date('' + (d.getFullYear()-1) + '/12/31'));
|
||||
}
|
||||
|
||||
return Date.ext.util.xPad(idow, 0);
|
||||
},
|
||||
w: 'getDay',
|
||||
W: function(d) {
|
||||
var doy = parseInt(Date.ext.formats.j(d), 10);
|
||||
var rdow = 7-Date.ext.formats.u(d);
|
||||
var woy = parseInt((doy+rdow)/7, 10);
|
||||
return Date.ext.util.xPad(woy, 0, 10);
|
||||
},
|
||||
y: function(d) { return Date.ext.util.xPad(d.getFullYear()%100, 0); },
|
||||
Y: 'getFullYear',
|
||||
z: function(d) {
|
||||
var o = d.getTimezoneOffset();
|
||||
var H = Date.ext.util.xPad(parseInt(Math.abs(o/60), 10), 0);
|
||||
var M = Date.ext.util.xPad(o%60, 0);
|
||||
return (o>0?'-':'+') + H + M;
|
||||
},
|
||||
Z: function(d) { return d.toString().replace(/^.*\(([^)]+)\)$/, '$1'); },
|
||||
'%': function(d) { return '%'; }
|
||||
};
|
||||
|
||||
/**
|
||||
\brief List of aggregate format specifiers.
|
||||
\details
|
||||
Aggregate format specifiers map to a combination of basic format specifiers.
|
||||
These are implemented in terms of Date.ext.formats.
|
||||
|
||||
A format specifier that maps to 'locale' is read from Date.ext.locales[current-locale].
|
||||
|
||||
\sa Date.ext.formats
|
||||
*/
|
||||
Date.ext.aggregates = {
|
||||
c: 'locale',
|
||||
D: '%m/%d/%y',
|
||||
h: '%b',
|
||||
n: '\n',
|
||||
r: '%I:%M:%S %p',
|
||||
R: '%H:%M',
|
||||
t: '\t',
|
||||
T: '%H:%M:%S',
|
||||
x: 'locale',
|
||||
X: 'locale'
|
||||
};
|
||||
|
||||
//! \cond FALSE
|
||||
// Cache timezone values because they will never change for a given JS instance
|
||||
Date.ext.aggregates.z = Date.ext.formats.z(new Date());
|
||||
Date.ext.aggregates.Z = Date.ext.formats.Z(new Date());
|
||||
//! \endcond
|
||||
|
||||
//! List of unsupported format specifiers.
|
||||
/**
|
||||
* \details
|
||||
* All format specifiers supported by the PHP implementation are supported by
|
||||
* this javascript implementation.
|
||||
*/
|
||||
Date.ext.unsupported = { };
|
||||
|
||||
|
||||
/**
|
||||
* \brief Formats the date according to the specified format.
|
||||
* \param fmt The format to format the date in. This may be a combination of the following:
|
||||
* \copydoc formats
|
||||
*
|
||||
* \return A string representation of the date formatted based on the passed in parameter
|
||||
* \sa http://www.php.net/strftime for documentation on format specifiers
|
||||
*/
|
||||
Date.prototype.strftime=function(fmt)
|
||||
{
|
||||
// Fix locale if declared locale hasn't been defined
|
||||
// After the first call this condition should never be entered unless someone changes the locale
|
||||
if(!(this.locale in Date.ext.locales))
|
||||
{
|
||||
if(this.locale.replace(/-[a-zA-Z]+$/, '') in Date.ext.locales)
|
||||
{
|
||||
this.locale = this.locale.replace(/-[a-zA-Z]+$/, '');
|
||||
}
|
||||
else
|
||||
{
|
||||
this.locale = 'en-GB';
|
||||
}
|
||||
}
|
||||
|
||||
var d = this;
|
||||
// First replace aggregates
|
||||
while(fmt.match(/%[cDhnrRtTxXzZ]/))
|
||||
{
|
||||
fmt = fmt.replace(/%([cDhnrRtTxXzZ])/g, function(m0, m1)
|
||||
{
|
||||
var f = Date.ext.aggregates[m1];
|
||||
return (f == 'locale' ? Date.ext.locales[d.locale][m1] : f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Now replace formats - we need a closure so that the date object gets passed through
|
||||
var str = fmt.replace(/%([aAbBCdegGHIjmMpPSuUVwWyY%])/g, function(m0, m1)
|
||||
{
|
||||
var f = Date.ext.formats[m1];
|
||||
if(typeof(f) == 'string') {
|
||||
return d[f]();
|
||||
} else if(typeof(f) == 'function') {
|
||||
return f.call(d, d);
|
||||
} else if(typeof(f) == 'object' && typeof(f[0]) == 'string') {
|
||||
return Date.ext.util.xPad(d[f[0]](), f[1]);
|
||||
} else {
|
||||
return m1;
|
||||
}
|
||||
});
|
||||
d=null;
|
||||
return str;
|
||||
};
|
||||
|
||||
/**
|
||||
* \mainpage strftime for Javascript
|
||||
*
|
||||
* \section toc Table of Contents
|
||||
* - \ref intro_sec
|
||||
* - <a class="el" href="strftime.js">Download full source</a> / <a class="el" href="strftime-min.js">minified</a>
|
||||
* - \subpage usage
|
||||
* - \subpage format_specifiers
|
||||
* - \subpage localisation
|
||||
* - \link strftime.js API Documentation \endlink
|
||||
* - \subpage demo
|
||||
* - \subpage changelog
|
||||
* - \subpage faq
|
||||
* - <a class="el" href="http://tech.bluesmoon.info/2008/04/strftime-in-javascript.html">Feedback</a>
|
||||
* - \subpage copyright_licence
|
||||
*
|
||||
* \section intro_sec Introduction
|
||||
*
|
||||
* C and PHP developers have had access to a built in strftime function for a long time.
|
||||
* This function is an easy way to format dates and times for various display needs.
|
||||
*
|
||||
* This library brings the flexibility of strftime to the javascript Date object
|
||||
*
|
||||
* Use this library if you frequently need to format dates in javascript in a variety of ways. For example,
|
||||
* if you have PHP code that writes out formatted dates, and want to mimic the functionality using
|
||||
* progressively enhanced javascript, then this library can do exactly what you want.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* \page usage Example usage
|
||||
*
|
||||
* \section usage_sec Usage
|
||||
* This library may be used as follows:
|
||||
* \code
|
||||
* var d = new Date();
|
||||
*
|
||||
* var ymd = d.strftime('%Y/%m/%d');
|
||||
* var iso = d.strftime('%Y-%m-%dT%H:%M:%S%z');
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* \subsection examples Examples
|
||||
*
|
||||
* To get the current time in hours and minutes:
|
||||
* \code
|
||||
* var d = new Date();
|
||||
* d.strftime("%H:%M");
|
||||
* \endcode
|
||||
*
|
||||
* To get the current time with seconds in AM/PM notation:
|
||||
* \code
|
||||
* var d = new Date();
|
||||
* d.strftime("%r");
|
||||
* \endcode
|
||||
*
|
||||
* To get the year and day of the year for August 23, 2009:
|
||||
* \code
|
||||
* var d = new Date('2009/8/23');
|
||||
* d.strftime("%Y-%j");
|
||||
* \endcode
|
||||
*
|
||||
* \section demo_sec Demo
|
||||
*
|
||||
* Try your own examples on the \subpage demo page. You can use any of the supported
|
||||
* \subpage format_specifiers.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* \page localisation Localisation
|
||||
* You can localise strftime by implementing the short and long forms for days of the
|
||||
* week and months of the year, and the localised aggregates for the preferred date
|
||||
* and time representation for your locale. You need to add your locale to the
|
||||
* Date.ext.locales object.
|
||||
*
|
||||
* \section localising_fr Localising for french
|
||||
*
|
||||
* For example, this is how we'd add French language strings to the locales object:
|
||||
* \dontinclude index.html
|
||||
* \skip Generic french
|
||||
* \until };
|
||||
* The % format specifiers are all defined in \ref formats. You can use any of those.
|
||||
*
|
||||
* This locale definition may be included in your own source file, or in the HTML file
|
||||
* including \c strftime.js, however it must be defined \em after including \c strftime.js
|
||||
*
|
||||
* The above definition includes generic french strings and formats that are used in France.
|
||||
* Other french speaking countries may have other representations for dates and times, so we
|
||||
* need to override this for them. For example, Canadian french uses a Y-m-d date format,
|
||||
* while French french uses d.m.Y. We fix this by defining Canadian french to be the same
|
||||
* as generic french, and then override the format specifiers for \c x for the \c fr-CA locale:
|
||||
* \until End french
|
||||
*
|
||||
* You can now use any of the French locales at any time by setting \link Date.prototype.locale Date.locale \endlink
|
||||
* to \c "fr", \c "fr-FR", \c "fr-CA", or any other french dialect:
|
||||
* \code
|
||||
* var d = new Date("2008/04/22");
|
||||
* d.locale = "fr";
|
||||
*
|
||||
* d.strftime("%A, %d %B == %x");
|
||||
* \endcode
|
||||
* will return:
|
||||
* \code
|
||||
* mardi, 22 avril == 22.04.2008
|
||||
* \endcode
|
||||
* While changing the locale to "fr-CA":
|
||||
* \code
|
||||
* d.locale = "fr-CA";
|
||||
*
|
||||
* d.strftime("%A, %d %B == %x");
|
||||
* \endcode
|
||||
* will return:
|
||||
* \code
|
||||
* mardi, 22 avril == 2008-04-22
|
||||
* \endcode
|
||||
*
|
||||
* You can use any of the format specifiers defined at \ref formats
|
||||
*
|
||||
* The locale for all dates defaults to the value of the \c lang attribute of your HTML document if
|
||||
* it is set, or to \c "en" otherwise.
|
||||
* \note
|
||||
* Your locale definitions \b MUST be added to the locale object before calling
|
||||
* \link Date.prototype.strftime Date.strftime \endlink.
|
||||
*
|
||||
* \sa \ref formats for a list of format specifiers that can be used in your definitions
|
||||
* for c, x and X.
|
||||
*
|
||||
* \section locale_names Locale names
|
||||
*
|
||||
* Locale names are defined in RFC 1766. Typically, a locale would be a two letter ISO639
|
||||
* defined language code and an optional ISO3166 defined country code separated by a -
|
||||
*
|
||||
* eg: fr-FR, de-DE, hi-IN
|
||||
*
|
||||
* \sa http://www.ietf.org/rfc/rfc1766.txt
|
||||
* \sa http://www.loc.gov/standards/iso639-2/php/code_list.php
|
||||
* \sa http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
|
||||
*
|
||||
* \section locale_fallback Locale fallbacks
|
||||
*
|
||||
* If a locale object corresponding to the fully specified locale isn't found, an attempt will be made
|
||||
* to fall back to the two letter language code. If a locale object corresponding to that isn't found
|
||||
* either, then the locale will fall back to \c "en". No warning will be issued.
|
||||
*
|
||||
* For example, if we define a locale for de:
|
||||
* \until };
|
||||
* Then set the locale to \c "de-DE":
|
||||
* \code
|
||||
* d.locale = "de-DE";
|
||||
*
|
||||
* d.strftime("%a, %d %b");
|
||||
* \endcode
|
||||
* In this case, the \c "de" locale will be used since \c "de-DE" has not been defined:
|
||||
* \code
|
||||
* Di, 22 Apr
|
||||
* \endcode
|
||||
*
|
||||
* Swiss german will return the same since it will also fall back to \c "de":
|
||||
* \code
|
||||
* d.locale = "de-CH";
|
||||
*
|
||||
* d.strftime("%a, %d %b");
|
||||
* \endcode
|
||||
* \code
|
||||
* Di, 22 Apr
|
||||
* \endcode
|
||||
*
|
||||
* We need to override the \c a specifier for Swiss german, since it's different from German german:
|
||||
* \until End german
|
||||
* We now get the correct results:
|
||||
* \code
|
||||
* d.locale = "de-CH";
|
||||
*
|
||||
* d.strftime("%a, %d %b");
|
||||
* \endcode
|
||||
* \code
|
||||
* Die, 22 Apr
|
||||
* \endcode
|
||||
*
|
||||
* \section builtin_locales Built in locales
|
||||
*
|
||||
* This library comes with pre-defined locales for en, en-GB, en-US and en-AU.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* \page format_specifiers Format specifiers
|
||||
*
|
||||
* \section specifiers Format specifiers
|
||||
* strftime has several format specifiers defined by the Open group at
|
||||
* http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html
|
||||
*
|
||||
* PHP added a few of its own, defined at http://www.php.net/strftime
|
||||
*
|
||||
* This javascript implementation supports all the PHP specifiers
|
||||
*
|
||||
* \subsection supp Supported format specifiers:
|
||||
* \copydoc formats
|
||||
*
|
||||
* \subsection unsupportedformats Unsupported format specifiers:
|
||||
* \copydoc unsupported
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* \page demo strftime demo
|
||||
* <div style="float:right;width:45%;">
|
||||
* \copydoc formats
|
||||
* </div>
|
||||
* \htmlinclude index.html
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* \page faq FAQ
|
||||
*
|
||||
* \section how_tos Usage
|
||||
*
|
||||
* \subsection howtouse Is there a manual on how to use this library?
|
||||
*
|
||||
* Yes, see \ref usage
|
||||
*
|
||||
* \subsection wheretoget Where can I get a minified version of this library?
|
||||
*
|
||||
* The minified version is available <a href="strftime-min.js" title="Minified strftime.js">here</a>.
|
||||
*
|
||||
* \subsection which_specifiers Which format specifiers are supported?
|
||||
*
|
||||
* See \ref format_specifiers
|
||||
*
|
||||
* \section whys Why?
|
||||
*
|
||||
* \subsection why_lib Why this library?
|
||||
*
|
||||
* I've used the strftime function in C, PHP and the Unix shell, and found it very useful
|
||||
* to do date formatting. When I needed to do date formatting in javascript, I decided
|
||||
* that it made the most sense to just reuse what I'm already familiar with.
|
||||
*
|
||||
* \subsection why_another Why another strftime implementation for Javascript?
|
||||
*
|
||||
* Yes, there are other strftime implementations for Javascript, but I saw problems with
|
||||
* all of them that meant I couldn't use them directly. Some implementations had bad
|
||||
* designs. For example, iterating through all possible specifiers and scanning the string
|
||||
* for them. Others were tied to specific libraries like prototype.
|
||||
*
|
||||
* Trying to extend any of the existing implementations would have required only slightly
|
||||
* less effort than writing this from scratch. In the end it took me just about 3 hours
|
||||
* to write the code and about 6 hours battling with doxygen to write these docs.
|
||||
*
|
||||
* I also had an idea of how I wanted to implement this, so decided to try it.
|
||||
*
|
||||
* \subsection why_extend_date Why extend the Date class rather than subclass it?
|
||||
*
|
||||
* I tried subclassing Date and failed. I didn't want to waste time on figuring
|
||||
* out if there was a problem in my code or if it just wasn't possible. Adding to the
|
||||
* Date.prototype worked well, so I stuck with it.
|
||||
*
|
||||
* I did have some worries because of the way for..in loops got messed up after json.js added
|
||||
* to the Object.prototype, but that isn't an issue here since {} is not a subclass of Date.
|
||||
*
|
||||
* My last doubt was about the Date.ext namespace that I created. I still don't like this,
|
||||
* but I felt that \c ext at least makes clear that this is external or an extension.
|
||||
*
|
||||
* It's quite possible that some future version of javascript will add an \c ext or a \c locale
|
||||
* or a \c strftime property/method to the Date class, but this library should probably
|
||||
* check for capabilities before doing what it does.
|
||||
*
|
||||
* \section curiosity Curiosity
|
||||
*
|
||||
* \subsection how_big How big is the code?
|
||||
*
|
||||
* \arg 26K bytes with documentation
|
||||
* \arg 4242 bytes minified using <a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a>
|
||||
* \arg 1477 bytes minified and gzipped
|
||||
*
|
||||
* \subsection how_long How long did it take to write this?
|
||||
*
|
||||
* 15 minutes for the idea while I was composing this blog post:
|
||||
* http://tech.bluesmoon.info/2008/04/javascript-date-functions.html
|
||||
*
|
||||
* 3 hours in one evening to write v1.0 of the code and 6 hours the same
|
||||
* night to write the docs and this manual. As you can tell, I'm fairly
|
||||
* sleepy.
|
||||
*
|
||||
* Versions 1.1 and 1.2 were done in a couple of hours each, and version 1.3
|
||||
* in under one hour.
|
||||
*
|
||||
* \section contributing Contributing
|
||||
*
|
||||
* \subsection how_to_rfe How can I request features or make suggestions?
|
||||
*
|
||||
* You can leave a comment on my blog post about this library here:
|
||||
* http://tech.bluesmoon.info/2008/04/strftime-in-javascript.html
|
||||
*
|
||||
* \subsection how_to_contribute Can I/How can I contribute code to this library?
|
||||
*
|
||||
* Yes, that would be very nice, thank you. You can do various things. You can make changes
|
||||
* to the library, and make a diff against the current file and mail me that diff at
|
||||
* philip@bluesmoon.info, or you could just host the new file on your own servers and add
|
||||
* your name to the copyright list at the top stating which parts you've added.
|
||||
*
|
||||
* If you do mail me a diff, let me know how you'd like to be listed in the copyright section.
|
||||
*
|
||||
* \subsection copyright_signover Who owns the copyright on contributed code?
|
||||
*
|
||||
* The contributor retains copyright on contributed code.
|
||||
*
|
||||
* In some cases I may use contributed code as a template and write the code myself. In this
|
||||
* case I'll give the contributor credit for the idea, but will not add their name to the
|
||||
* copyright holders list.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* \page copyright_licence Copyright & Licence
|
||||
*
|
||||
* \section copyright Copyright
|
||||
* \dontinclude strftime.js
|
||||
* \skip Copyright
|
||||
* \until rights
|
||||
*
|
||||
* \section licence Licence
|
||||
* \skip This code
|
||||
* \until SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
*
|
||||
* \page changelog ChangeLog
|
||||
*
|
||||
* \par 1.3 - 2008/06/17:
|
||||
* - Fixed padding issue with negative timezone offsets in %r
|
||||
* reported and fixed by Mikko <mikko.heimola@iki.fi>
|
||||
* - Added support for %P
|
||||
* - Internationalised %r, %p and %P
|
||||
*
|
||||
* \par 1.2 - 2008/04/27:
|
||||
* - Fixed support for c (previously it just returned toLocaleString())
|
||||
* - Add support for c, x and X
|
||||
* - Add locales for en-GB, en-US and en-AU
|
||||
* - Make en-GB the default locale (previous was en)
|
||||
* - Added more localisation docs
|
||||
*
|
||||
* \par 1.1 - 2008/04/27:
|
||||
* - Fix bug in xPad which wasn't padding more than a single digit
|
||||
* - Fix bug in j which had an off by one error for days after March 10th because of daylight savings
|
||||
* - Add support for g, G, U, V and W
|
||||
*
|
||||
* \par 1.0 - 2008/04/22:
|
||||
* - Initial release with support for a, A, b, B, c, C, d, D, e, H, I, j, m, M, p, r, R, S, t, T, u, w, y, Y, z, Z, and %
|
||||
*/
|
||||
@@ -1,11 +1,17 @@
|
||||
/* TODO: separate openerp web client page css from openerp views css */
|
||||
body {
|
||||
body.openerp {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
height: 100%;
|
||||
min-width: 1000px;
|
||||
overflow-y: scroll;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp option, .openerp button, .openerp .ui-widget {
|
||||
font-family: Ubuntu, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.oe_box {
|
||||
border: 1px solid #aaf;
|
||||
padding: 2px;
|
||||
@@ -20,13 +26,6 @@ body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
body.openerp {
|
||||
height: 100%;
|
||||
min-width: 1000px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.openerp .oe-number {
|
||||
text-align: right !important;
|
||||
}
|
||||
@@ -120,7 +119,6 @@ body.openerp {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
color: white;
|
||||
font-family: Ubuntu, Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding: 5px;
|
||||
@@ -381,7 +379,7 @@ label.error {
|
||||
/* Header */
|
||||
.openerp .header {
|
||||
height: 65px;
|
||||
background: url("../img/header-background.png") repeat-x scroll left top transparent;
|
||||
background: url("/base/static/src/img/header-background.png") repeat-x scroll left top transparent;
|
||||
color: #FFFFFF;
|
||||
letter-spacing: 0.5px;
|
||||
text-shadow: 0 1px 0 #333333;
|
||||
@@ -497,7 +495,6 @@ label.error {
|
||||
color: #666666;
|
||||
font-weight: bold;
|
||||
font-size: 0.8em;
|
||||
font-family: Ubuntu, Helvetica, sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
.openerp div.oe_footer p.oe_footer_powered a {
|
||||
@@ -515,7 +512,6 @@ label.error {
|
||||
.openerp h2.oe_view_title {
|
||||
font-size: 175%;
|
||||
font-weight: normal;
|
||||
font-family: Ubuntu, Helvetica, sans-serif;
|
||||
margin: 2px 0;
|
||||
color: #252424;
|
||||
text-shadow: white 0 1px 0;
|
||||
@@ -859,7 +855,7 @@ label.error {
|
||||
-webkit-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
padding: 2px;
|
||||
padding: 0 2px 0 2px;
|
||||
border: 1px solid #999;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
@@ -988,7 +984,6 @@ label.error {
|
||||
margin: 0;
|
||||
width: 180px;
|
||||
height: 100%;
|
||||
font-family: Ubuntu, Helvetica, sans-serif;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
@@ -1046,7 +1041,6 @@ label.error {
|
||||
|
||||
.openerp .view-manager-main-sidebar h2 {
|
||||
margin:0;
|
||||
font-family: Ubuntu, Helvetica, sans-serif;
|
||||
font-size: 1.15em;
|
||||
color: #8E8E8E;
|
||||
text-shadow: white 0 1px 0;
|
||||
|
||||
@@ -12,10 +12,7 @@
|
||||
return;
|
||||
var session_counter = 0;
|
||||
|
||||
/** @lends openerp */
|
||||
var openerp = this.openerp = {
|
||||
// debug flag
|
||||
debug: true,
|
||||
// Per session namespace
|
||||
// openerp.<module> will map to
|
||||
// openerp.sessions.sessionname.<module> using a closure
|
||||
@@ -44,7 +41,6 @@
|
||||
}
|
||||
return new_instance;
|
||||
}
|
||||
// TODO add initrpc to init core only for RPC
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -54,35 +50,15 @@
|
||||
|
||||
openerp.base = function(instance) {
|
||||
openerp.base.core(instance);
|
||||
openerp.base.dates(instance);
|
||||
openerp.base.formats(instance);
|
||||
openerp.base.chrome(instance);
|
||||
openerp.base.data(instance);
|
||||
if (openerp.base.views) {
|
||||
openerp.base.views(instance);
|
||||
}
|
||||
if (openerp.base.search) {
|
||||
openerp.base.search(instance);
|
||||
}
|
||||
if (openerp.base.list) {
|
||||
openerp.base.list(instance);
|
||||
}
|
||||
if (openerp.base. m2o) {
|
||||
openerp.base.m2o(instance);
|
||||
}
|
||||
if (openerp.base.form) {
|
||||
openerp.base.form(instance);
|
||||
}
|
||||
if (openerp.base.list && openerp.base.list.editable) {
|
||||
openerp.base.list.editable(instance);
|
||||
}
|
||||
if (openerp.web_mobile) {
|
||||
openerp.web_mobile(instance);
|
||||
}
|
||||
if (openerp.base.view_tree) {
|
||||
openerp.base.view_tree(instance);
|
||||
}
|
||||
if (openerp.base.data_export) {
|
||||
openerp.base.data_export(instance);
|
||||
files = ["views","search","list","form","list_editable","web_mobile","view_tree","data_export"];
|
||||
for(i=0; i<files.length; i++) {
|
||||
if(openerp.base[files[i]]) {
|
||||
openerp.base[files[i]](instance);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@ openerp.base.Dialog = openerp.base.OldWidget.extend({
|
||||
}
|
||||
this.set_options(dialog_options);
|
||||
this.$dialog.dialog(this.dialog_options).dialog('open');
|
||||
return this;
|
||||
},
|
||||
close: function() {
|
||||
// Closes the dialog but leave it in a state where it could be opened again.
|
||||
@@ -291,8 +292,7 @@ openerp.base.Database = openerp.base.Widget.extend({
|
||||
},
|
||||
do_create: function() {
|
||||
var self = this;
|
||||
self.$option_id.html(QWeb.render("CreateDB", self));
|
||||
|
||||
self.$option_id.html(QWeb.render("Database.CreateDB", self));
|
||||
self.$option_id.find("form[name=create_db_form]").validate({
|
||||
submitHandler: function (form) {
|
||||
var fields = $(form).serializeArray();
|
||||
@@ -314,11 +314,9 @@ openerp.base.Database = openerp.base.Widget.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
do_drop: function() {
|
||||
var self = this;
|
||||
self.$option_id.html(QWeb.render("DropDB", self));
|
||||
|
||||
self.$option_id.find("form[name=drop_db_form]").validate({
|
||||
submitHandler: function (form) {
|
||||
var $form = $(form),
|
||||
@@ -341,7 +339,6 @@ openerp.base.Database = openerp.base.Widget.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
wait_for_file: function (token, cleanup) {
|
||||
var self = this,
|
||||
cookie_name = 'fileToken',
|
||||
@@ -362,7 +359,7 @@ openerp.base.Database = openerp.base.Widget.extend({
|
||||
|
||||
if (cleanup) { cleanup(); }
|
||||
}
|
||||
}, 100);
|
||||
}, 200);
|
||||
},
|
||||
do_backup: function() {
|
||||
var self = this;
|
||||
@@ -402,7 +399,6 @@ openerp.base.Database = openerp.base.Widget.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
do_restore: function() {
|
||||
var self = this;
|
||||
self.$option_id.html(QWeb.render("RestoreDB", self));
|
||||
@@ -441,7 +437,6 @@ openerp.base.Database = openerp.base.Widget.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
do_change_password: function() {
|
||||
var self = this;
|
||||
self.$option_id.html(QWeb.render("Change_DB_Pwd", self));
|
||||
@@ -836,13 +831,6 @@ openerp.base.WebClient = openerp.base.Widget.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.webclient = function(element_id) {
|
||||
// TODO Helper to start webclient rename it openerp.base.webclient
|
||||
var client = new openerp.base.WebClient(element_id);
|
||||
client.start();
|
||||
return client;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
||||
+288
-290
@@ -323,6 +323,293 @@ openerp.base.CallbackEnabled = openerp.base.Class.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.Session = openerp.base.CallbackEnabled.extend( /** @lends openerp.base.Session# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @param server
|
||||
* @param port
|
||||
*/
|
||||
init: function(server, port) {
|
||||
this._super();
|
||||
this.server = (server == undefined) ? location.hostname : server;
|
||||
this.port = (port == undefined) ? location.port : port;
|
||||
this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp";
|
||||
this.debug = (window.location.search.indexOf('?debug') !== -1);
|
||||
this.db = "";
|
||||
this.login = "";
|
||||
this.password = "";
|
||||
this.user_context= {};
|
||||
this.uid = false;
|
||||
this.session_id = false;
|
||||
this.module_list = [];
|
||||
this.module_loaded = {"base": true};
|
||||
this.context = {};
|
||||
this.shortcuts = [];
|
||||
this.active_id = null;
|
||||
this.session = this;
|
||||
},
|
||||
start: function() {
|
||||
this.session_restore();
|
||||
},
|
||||
/**
|
||||
* Executes an RPC call, registering the provided callbacks.
|
||||
*
|
||||
* Registers a default error callback if none is provided, and handles
|
||||
* setting the correct session id and session context in the parameter
|
||||
* objects
|
||||
*
|
||||
* @param {String} url RPC endpoint
|
||||
* @param {Object} params call parameters
|
||||
* @param {Function} success_callback function to execute on RPC call success
|
||||
* @param {Function} error_callback function to execute on RPC call failure
|
||||
* @returns {jQuery.Deferred} jquery-provided ajax deferred
|
||||
*/
|
||||
rpc: function(url, params, success_callback, error_callback) {
|
||||
var self = this;
|
||||
// Construct a JSON-RPC2 request, method is currently unused
|
||||
params.session_id = this.session_id;
|
||||
|
||||
// Call using the rpc_mode
|
||||
var deferred = $.Deferred();
|
||||
this.rpc_ajax(url, {
|
||||
jsonrpc: "2.0",
|
||||
method: "call",
|
||||
params: params,
|
||||
id:null
|
||||
}).then(function () {deferred.resolve.apply(deferred, arguments);},
|
||||
function(error) {deferred.reject(error, $.Event());});
|
||||
return deferred.fail(function() {
|
||||
deferred.fail(function(error, event) {
|
||||
if (!event.isDefaultPrevented()) {
|
||||
self.on_rpc_error(error, event);
|
||||
}
|
||||
});
|
||||
}).then(success_callback, error_callback).promise();
|
||||
},
|
||||
/**
|
||||
* Raw JSON-RPC call
|
||||
*
|
||||
* @returns {jQuery.Deferred} ajax-based deferred object
|
||||
*/
|
||||
rpc_ajax: function(url, payload) {
|
||||
var self = this;
|
||||
this.on_rpc_request();
|
||||
// url can be an $.ajax option object
|
||||
if (_.isString(url)) {
|
||||
url = {
|
||||
url: url
|
||||
}
|
||||
}
|
||||
var ajax = _.extend({
|
||||
type: "POST",
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(payload),
|
||||
processData: false
|
||||
}, url);
|
||||
var deferred = $.Deferred();
|
||||
$.ajax(ajax).done(function(response, textStatus, jqXHR) {
|
||||
self.on_rpc_response();
|
||||
if (!response.error) {
|
||||
deferred.resolve(response["result"], textStatus, jqXHR);
|
||||
return;
|
||||
}
|
||||
if (response.error.data.type !== "session_invalid") {
|
||||
deferred.reject(response.error);
|
||||
return;
|
||||
}
|
||||
self.uid = false;
|
||||
self.on_session_invalid(function() {
|
||||
self.rpc(url, payload.params,
|
||||
function() {
|
||||
deferred.resolve.apply(deferred, arguments);
|
||||
},
|
||||
function(error, event) {
|
||||
event.preventDefault();
|
||||
deferred.reject.apply(deferred, arguments);
|
||||
});
|
||||
});
|
||||
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||
self.on_rpc_response();
|
||||
var error = {
|
||||
code: -32098,
|
||||
message: "XmlHttpRequestError " + errorThrown,
|
||||
data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] }
|
||||
};
|
||||
deferred.reject(error);
|
||||
});
|
||||
return deferred.promise();
|
||||
},
|
||||
on_rpc_request: function() {
|
||||
},
|
||||
on_rpc_response: function() {
|
||||
},
|
||||
on_rpc_error: function(error) {
|
||||
},
|
||||
/**
|
||||
* The session is validated either by login or by restoration of a previous session
|
||||
*/
|
||||
on_session_valid: function() {
|
||||
if(!openerp._modules_loaded)
|
||||
this.load_modules();
|
||||
},
|
||||
on_session_invalid: function(contination) {
|
||||
},
|
||||
session_is_valid: function() {
|
||||
return this.uid;
|
||||
},
|
||||
session_login: function(db, login, password, success_callback) {
|
||||
var self = this;
|
||||
this.db = db;
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
var params = { db: this.db, login: this.login, password: this.password };
|
||||
this.rpc("/base/session/login", params, function(result) {
|
||||
self.session_id = result.session_id;
|
||||
self.uid = result.uid;
|
||||
self.user_context = result.context;
|
||||
self.session_save();
|
||||
self.on_session_valid();
|
||||
if (success_callback)
|
||||
success_callback();
|
||||
});
|
||||
},
|
||||
session_logout: function() {
|
||||
this.uid = false;
|
||||
},
|
||||
/**
|
||||
* Reloads uid and session_id from local storage, if they exist
|
||||
*/
|
||||
session_restore: function () {
|
||||
this.uid = this.get_cookie('uid');
|
||||
this.session_id = this.get_cookie('session_id');
|
||||
this.db = this.get_cookie('db');
|
||||
this.login = this.get_cookie('login');
|
||||
this.user_context = this.get_cookie("user_context");
|
||||
// we should do an rpc to confirm that this session_id is valid and if it is retrieve the information about db and login
|
||||
// then call on_session_valid
|
||||
this.on_session_valid();
|
||||
},
|
||||
/**
|
||||
* Saves the session id and uid locally
|
||||
*/
|
||||
session_save: function () {
|
||||
this.set_cookie('uid', this.uid);
|
||||
this.set_cookie('session_id', this.session_id);
|
||||
this.set_cookie('db', this.db);
|
||||
this.set_cookie('login', this.login);
|
||||
this.set_cookie('user_context', this.user_context);
|
||||
},
|
||||
logout: function() {
|
||||
delete this.uid;
|
||||
delete this.session_id;
|
||||
delete this.db;
|
||||
delete this.login;
|
||||
this.set_cookie('uid', '');
|
||||
this.set_cookie('session_id', '');
|
||||
this.set_cookie('db', '');
|
||||
this.set_cookie('login', '');
|
||||
this.on_session_invalid(function() {});
|
||||
},
|
||||
/**
|
||||
* Fetches a cookie stored by an openerp session
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
*/
|
||||
get_cookie: function (name) {
|
||||
var nameEQ = this.element_id + '|' + name + '=';
|
||||
var cookies = document.cookie.split(';');
|
||||
for(var i=0; i<cookies.length; ++i) {
|
||||
var cookie = cookies[i].replace(/^\s*/, '');
|
||||
if(cookie.indexOf(nameEQ) === 0) {
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* Create a new cookie with the provided name and value
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
* @param value the cookie's value
|
||||
* @param ttl the cookie's time to live, 1 year by default, set to -1 to delete
|
||||
*/
|
||||
set_cookie: function (name, value, ttl) {
|
||||
ttl = ttl || 24*60*60*365;
|
||||
document.cookie = [
|
||||
this.element_id + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)),
|
||||
'max-age=' + ttl,
|
||||
'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString()
|
||||
].join(';');
|
||||
},
|
||||
/**
|
||||
* Load additional web addons of that instance and init them
|
||||
*/
|
||||
load_modules: function() {
|
||||
var self = this;
|
||||
this.rpc('/base/session/modules', {}, function(result) {
|
||||
self.module_list = result;
|
||||
var lang = self.user_context.lang;
|
||||
params = { mods: ["base"].concat(result), lang: lang};
|
||||
self.rpc('/base/webclient/translations',params).then(function(transs) {
|
||||
openerp.base._t.database.set_bundle(transs);
|
||||
var modules = self.module_list.join(',');
|
||||
if(self.debug) {
|
||||
self.rpc('/base/webclient/csslist', {"mods": modules}, self.do_load_css);
|
||||
self.rpc('/base/webclient/jslist', {"mods": modules}, self.do_load_js);
|
||||
} else {
|
||||
self.do_load_css(["/base/webclient/css?mods="+modules]);
|
||||
self.do_load_js(["/base/webclient/js?mods="+modules]);
|
||||
}
|
||||
openerp._modules_loaded = true;
|
||||
});
|
||||
});
|
||||
},
|
||||
do_load_css: function (files) {
|
||||
_.each(files, function (file) {
|
||||
$('head').append($('<link>', {
|
||||
'href': file,
|
||||
'rel': 'stylesheet',
|
||||
'type': 'text/css'
|
||||
}));
|
||||
});
|
||||
},
|
||||
do_load_js: function(files) {
|
||||
var self = this;
|
||||
if(files.length != 0) {
|
||||
var file = files.shift();
|
||||
var tag = document.createElement('script');
|
||||
tag.type = 'text/javascript';
|
||||
tag.src = file;
|
||||
tag.onload = tag.onreadystatechange = function() {
|
||||
if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done )
|
||||
return;
|
||||
tag.onload_done = true;
|
||||
self.do_load_js(files);
|
||||
};
|
||||
document.head.appendChild(tag);
|
||||
} else {
|
||||
this.on_modules_loaded();
|
||||
}
|
||||
},
|
||||
on_modules_loaded: function() {
|
||||
for(var j=0; j<this.module_list.length; j++) {
|
||||
var mod = this.module_list[j];
|
||||
if(this.module_loaded[mod])
|
||||
continue;
|
||||
openerp[mod] = {};
|
||||
// init module mod
|
||||
if(openerp._openerp[mod] != undefined) {
|
||||
openerp._openerp[mod](openerp);
|
||||
this.module_loaded[mod] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Utility class that any class is allowed to extend to easy common manipulations.
|
||||
*
|
||||
@@ -355,7 +642,7 @@ openerp.base.SessionAware = openerp.base.CallbackEnabled.extend({
|
||||
this.on_log.apply(this,args);
|
||||
},
|
||||
on_log: function() {
|
||||
if(window.openerp.debug || (window.location.search.indexOf('?debug') !== -1)) {
|
||||
if(this.session.debug) {
|
||||
var notify = false;
|
||||
var body = false;
|
||||
if(window.console) {
|
||||
@@ -616,295 +903,6 @@ openerp.base.TranslationDataBase = openerp.base.Class.extend({
|
||||
|
||||
openerp.base._t = new openerp.base.TranslationDataBase().build_translation_function();
|
||||
|
||||
openerp.base.Session = openerp.base.CallbackEnabled.extend( /** @lends openerp.base.Session# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @param element_id to use for exception reporting
|
||||
* @param server
|
||||
* @param port
|
||||
*/
|
||||
init: function(server, port) {
|
||||
this._super();
|
||||
this.server = (server == undefined) ? location.hostname : server;
|
||||
this.port = (port == undefined) ? location.port : port;
|
||||
this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp";
|
||||
this.debug = true;
|
||||
this.db = "";
|
||||
this.login = "";
|
||||
this.password = "";
|
||||
this.user_context= {};
|
||||
this.uid = false;
|
||||
this.session_id = false;
|
||||
this.module_list = [];
|
||||
this.module_loaded = {"base": true};
|
||||
this.context = {};
|
||||
this.shortcuts = [];
|
||||
this.active_id = null;
|
||||
},
|
||||
start: function() {
|
||||
this.session_restore();
|
||||
},
|
||||
/**
|
||||
* Executes an RPC call, registering the provided callbacks.
|
||||
*
|
||||
* Registers a default error callback if none is provided, and handles
|
||||
* setting the correct session id and session context in the parameter
|
||||
* objects
|
||||
*
|
||||
* @param {String} url RPC endpoint
|
||||
* @param {Object} params call parameters
|
||||
* @param {Function} success_callback function to execute on RPC call success
|
||||
* @param {Function} error_callback function to execute on RPC call failure
|
||||
* @returns {jQuery.Deferred} jquery-provided ajax deferred
|
||||
*/
|
||||
rpc: function(url, params, success_callback, error_callback) {
|
||||
var self = this;
|
||||
// Construct a JSON-RPC2 request, method is currently unused
|
||||
params.session_id = this.session_id;
|
||||
|
||||
// Call using the rpc_mode
|
||||
var deferred = $.Deferred();
|
||||
this.rpc_ajax(url, {
|
||||
jsonrpc: "2.0",
|
||||
method: "call",
|
||||
params: params,
|
||||
id:null
|
||||
}).then(function () {deferred.resolve.apply(deferred, arguments);},
|
||||
function(error) {deferred.reject(error, $.Event());});
|
||||
return deferred.fail(function() {
|
||||
deferred.fail(function(error, event) {
|
||||
if (!event.isDefaultPrevented()) {
|
||||
self.on_rpc_error(error, event);
|
||||
}
|
||||
});
|
||||
}).then(success_callback, error_callback).promise();
|
||||
},
|
||||
/**
|
||||
* Raw JSON-RPC call
|
||||
*
|
||||
* @returns {jQuery.Deferred} ajax-based deferred object
|
||||
*/
|
||||
rpc_ajax: function(url, payload) {
|
||||
var self = this;
|
||||
this.on_rpc_request();
|
||||
// url can be an $.ajax option object
|
||||
if (_.isString(url)) {
|
||||
url = {
|
||||
url: url
|
||||
}
|
||||
}
|
||||
var ajax = _.extend({
|
||||
type: "POST",
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(payload),
|
||||
processData: false
|
||||
}, url);
|
||||
var deferred = $.Deferred();
|
||||
$.ajax(ajax).done(function(response, textStatus, jqXHR) {
|
||||
self.on_rpc_response();
|
||||
if (!response.error) {
|
||||
deferred.resolve(response["result"], textStatus, jqXHR);
|
||||
return;
|
||||
}
|
||||
if (response.error.data.type !== "session_invalid") {
|
||||
deferred.reject(response.error);
|
||||
return;
|
||||
}
|
||||
self.uid = false;
|
||||
self.on_session_invalid(function() {
|
||||
self.rpc(url, payload.params,
|
||||
function() {
|
||||
deferred.resolve.apply(deferred, arguments);
|
||||
},
|
||||
function(error, event) {
|
||||
event.preventDefault();
|
||||
deferred.reject.apply(deferred, arguments);
|
||||
});
|
||||
});
|
||||
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||
self.on_rpc_response();
|
||||
var error = {
|
||||
code: -32098,
|
||||
message: "XmlHttpRequestError " + errorThrown,
|
||||
data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] }
|
||||
};
|
||||
deferred.reject(error);
|
||||
});
|
||||
return deferred.promise();
|
||||
},
|
||||
on_rpc_request: function() {
|
||||
},
|
||||
on_rpc_response: function() {
|
||||
},
|
||||
on_rpc_error: function(error) {
|
||||
},
|
||||
/**
|
||||
* The session is validated either by login or by restoration of a previous session
|
||||
*/
|
||||
on_session_valid: function() {
|
||||
if(!openerp._modules_loaded)
|
||||
this.load_modules();
|
||||
},
|
||||
on_session_invalid: function(contination) {
|
||||
},
|
||||
session_is_valid: function() {
|
||||
return this.uid;
|
||||
},
|
||||
session_login: function(db, login, password, success_callback) {
|
||||
var self = this;
|
||||
this.db = db;
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
var params = { db: this.db, login: this.login, password: this.password };
|
||||
this.rpc("/base/session/login", params, function(result) {
|
||||
self.session_id = result.session_id;
|
||||
self.uid = result.uid;
|
||||
self.user_context = result.context;
|
||||
self.session_save();
|
||||
self.on_session_valid();
|
||||
if (success_callback)
|
||||
success_callback();
|
||||
});
|
||||
},
|
||||
session_logout: function() {
|
||||
this.uid = false;
|
||||
},
|
||||
/**
|
||||
* Reloads uid and session_id from local storage, if they exist
|
||||
*/
|
||||
session_restore: function () {
|
||||
this.uid = this.get_cookie('uid');
|
||||
this.session_id = this.get_cookie('session_id');
|
||||
this.db = this.get_cookie('db');
|
||||
this.login = this.get_cookie('login');
|
||||
this.user_context = this.get_cookie("user_context");
|
||||
// we should do an rpc to confirm that this session_id is valid and if it is retrieve the information about db and login
|
||||
// then call on_session_valid
|
||||
this.on_session_valid();
|
||||
},
|
||||
/**
|
||||
* Saves the session id and uid locally
|
||||
*/
|
||||
session_save: function () {
|
||||
this.set_cookie('uid', this.uid);
|
||||
this.set_cookie('session_id', this.session_id);
|
||||
this.set_cookie('db', this.db);
|
||||
this.set_cookie('login', this.login);
|
||||
this.set_cookie('user_context', this.user_context);
|
||||
},
|
||||
logout: function() {
|
||||
delete this.uid;
|
||||
delete this.session_id;
|
||||
delete this.db;
|
||||
delete this.login;
|
||||
this.set_cookie('uid', '');
|
||||
this.set_cookie('session_id', '');
|
||||
this.set_cookie('db', '');
|
||||
this.set_cookie('login', '');
|
||||
this.on_session_invalid(function() {});
|
||||
},
|
||||
/**
|
||||
* Fetches a cookie stored by an openerp session
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
*/
|
||||
get_cookie: function (name) {
|
||||
var nameEQ = this.element_id + '|' + name + '=';
|
||||
var cookies = document.cookie.split(';');
|
||||
for(var i=0; i<cookies.length; ++i) {
|
||||
var cookie = cookies[i].replace(/^\s*/, '');
|
||||
if(cookie.indexOf(nameEQ) === 0) {
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* Create a new cookie with the provided name and value
|
||||
*
|
||||
* @private
|
||||
* @param name the cookie's name
|
||||
* @param value the cookie's value
|
||||
* @param ttl the cookie's time to live, 1 year by default, set to -1 to delete
|
||||
*/
|
||||
set_cookie: function (name, value, ttl) {
|
||||
ttl = ttl || 24*60*60*365;
|
||||
document.cookie = [
|
||||
this.element_id + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)),
|
||||
'max-age=' + ttl,
|
||||
'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString()
|
||||
].join(';');
|
||||
},
|
||||
/**
|
||||
* Load additional web addons of that instance and init them
|
||||
*/
|
||||
load_modules: function() {
|
||||
var self = this;
|
||||
this.rpc('/base/session/modules', {}, function(result) {
|
||||
self.module_list = result;
|
||||
var lang = self.user_context.lang;
|
||||
self.rpc('/base/webclient/translations',{
|
||||
mods: ["base"].concat(result),
|
||||
lang: lang})
|
||||
.then(function(transs) {
|
||||
openerp.base._t.database.set_bundle(transs);
|
||||
var modules = self.module_list.join(',');
|
||||
if(self.debug || true) {
|
||||
self.rpc('/base/webclient/csslist', {"mods": modules}, self.do_load_css);
|
||||
self.rpc('/base/webclient/jslist', {"mods": modules}, self.do_load_js);
|
||||
} else {
|
||||
self.do_load_css(["/base/webclient/css?mods="+modules]);
|
||||
self.do_load_js(["/base/webclient/js?mods="+modules]);
|
||||
}
|
||||
openerp._modules_loaded = true;
|
||||
});
|
||||
});
|
||||
},
|
||||
do_load_css: function (files) {
|
||||
_.each(files, function (file) {
|
||||
$('head').append($('<link>', {
|
||||
'href': file,
|
||||
'rel': 'stylesheet',
|
||||
'type': 'text/css'
|
||||
}));
|
||||
});
|
||||
},
|
||||
do_load_js: function(files) {
|
||||
var self = this;
|
||||
if(files.length != 0) {
|
||||
var file = files.shift();
|
||||
var tag = document.createElement('script');
|
||||
tag.type = 'text/javascript';
|
||||
tag.src = file;
|
||||
tag.onload = tag.onreadystatechange = function() {
|
||||
if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done )
|
||||
return;
|
||||
tag.onload_done = true;
|
||||
self.do_load_js(files);
|
||||
};
|
||||
document.head.appendChild(tag);
|
||||
} else {
|
||||
this.on_modules_loaded();
|
||||
}
|
||||
},
|
||||
on_modules_loaded: function() {
|
||||
for(var j=0; j<this.module_list.length; j++) {
|
||||
var mod = this.module_list[j];
|
||||
if(this.module_loaded[mod])
|
||||
continue;
|
||||
openerp[mod] = {};
|
||||
// init module mod
|
||||
if(openerp._openerp[mod] != undefined) {
|
||||
openerp._openerp[mod](openerp);
|
||||
this.module_loaded[mod] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
||||
@@ -286,14 +286,16 @@ openerp.base.DataSet = openerp.base.Widget.extend( /** @lends openerp.base.Data
|
||||
* Read a slice of the records represented by this DataSet, based on its
|
||||
* domain and context.
|
||||
*
|
||||
* @param {Array} [fields] fields to read and return, by default all fields are returned
|
||||
* @params {Object} options
|
||||
* @param {Array} [options.fields] fields to read and return, by default all fields are returned
|
||||
* @param {Number} [options.offset=0] The index from which selected records should be returned
|
||||
* @param {Number} [options.limit=null] The maximum number of records to return
|
||||
* @param {Function} callback function called with read_slice result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_slice: function (options, callback) { return null; },
|
||||
read_slice: function (fields, options, callback) {
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* Reads the current dataset record (from its index)
|
||||
*
|
||||
@@ -478,11 +480,12 @@ openerp.base.DataSetStatic = openerp.base.DataSet.extend({
|
||||
// all local records
|
||||
this.ids = ids || [];
|
||||
},
|
||||
read_slice: function (options, callback) {
|
||||
read_slice: function (fields, options, callback) {
|
||||
// TODO remove fields from options
|
||||
var self = this,
|
||||
offset = options.offset || 0,
|
||||
limit = options.limit || false,
|
||||
fields = options.fields || false;
|
||||
fields = fields || false;
|
||||
var end_pos = limit && limit !== -1 ? offset + limit : undefined;
|
||||
return this.read_ids(this.ids.slice(offset, end_pos), fields, callback);
|
||||
},
|
||||
@@ -532,12 +535,13 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
||||
* @param {Function} callback function called with read_slice result
|
||||
* @returns {$.Deferred}
|
||||
*/
|
||||
read_slice: function (options, callback) {
|
||||
read_slice: function (fields, options, callback) {
|
||||
var self = this;
|
||||
var options = options || {};
|
||||
var offset = options.offset || 0;
|
||||
return this.rpc('/base/dataset/search_read', {
|
||||
model: this.model,
|
||||
fields: options.fields || false,
|
||||
fields: fields || false,
|
||||
domain: this.get_domain(options.domain),
|
||||
context: this.get_context(options.context),
|
||||
sort: this.sort(),
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
|
||||
openerp.base.dates = function(openerp) {
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
*
|
||||
* The timezone is assumed to be UTC (standard for OpenERP 6.1)
|
||||
* and will be converted to the browser's timezone.
|
||||
*
|
||||
* @param {String} str A string representing a datetime.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.str_to_datetime = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
var obj = Date.parse(str + " GMT");
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* date string format (exemple: '2011-12-01').
|
||||
*
|
||||
* @param {String} str A string representing a date.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.str_to_date = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* time string format (exemple: '15:12:35').
|
||||
*
|
||||
* @param {String} str A string representing a time.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.str_to_time = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/*
|
||||
* Left-pad provided arg 1 with zeroes until reaching size provided by second
|
||||
* argument.
|
||||
*
|
||||
* @param {Number|String} str value to pad
|
||||
* @param {Number} size size to reach on the final padded value
|
||||
* @returns {String} padded string
|
||||
*/
|
||||
var zpad = function(str, size) {
|
||||
str = "" + str;
|
||||
return new Array(size - str.length + 1).join('0') + str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
*
|
||||
* The timezone of the Date object is assumed to be the one of the
|
||||
* browser and it will be converted to UTC (standard for OpenERP 6.1).
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a datetime.
|
||||
*/
|
||||
openerp.base.datetime_to_str = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getUTCFullYear(),4) + "-" + zpad(obj.getUTCMonth() + 1,2) + "-"
|
||||
+ zpad(obj.getUTCDate(),2) + " " + zpad(obj.getUTCHours(),2) + ":"
|
||||
+ zpad(obj.getUTCMinutes(),2) + ":" + zpad(obj.getUTCSeconds(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* date string format (exemple: '2011-12-01').
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a date.
|
||||
*/
|
||||
openerp.base.date_to_str = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getFullYear(),4) + "-" + zpad(obj.getMonth() + 1,2) + "-"
|
||||
+ zpad(obj.getDate(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* time string format (exemple: '15:12:35').
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a time.
|
||||
*/
|
||||
openerp.base.time_to_str = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getHours(),2) + ":" + zpad(obj.getMinutes(),2) + ":"
|
||||
+ zpad(obj.getSeconds(),2);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
openerp.base.form = function (openerp) {
|
||||
|
||||
|
||||
var _t = openerp.base._t;
|
||||
|
||||
openerp.base.views.add('form', 'openerp.base.FormView');
|
||||
@@ -346,7 +346,10 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
setTimeout(function() {
|
||||
self.on_saved({ result: true }, success);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
},
|
||||
do_save_edit: function() {
|
||||
@@ -458,9 +461,7 @@ openerp.base.form.SidebarAttachments = openerp.base.Widget.extend({
|
||||
['res_model', '=', this.view.dataset.model],
|
||||
['res_id', '=', this.view.datarecord.id],
|
||||
['type', 'in', ['binary', 'url']]
|
||||
])).read_slice(
|
||||
{fields: ['name', 'url', 'type']},
|
||||
this.on_attachments_loaded);
|
||||
])).read_slice(['name', 'url', 'type'], this.on_attachments_loaded);
|
||||
}
|
||||
},
|
||||
on_attachments_loaded: function(attachments) {
|
||||
@@ -811,6 +812,7 @@ openerp.base.form.WidgetLabel = openerp.base.form.Widget.extend({
|
||||
this.$element.find("label").dblclick(function() {
|
||||
var widget = self['for'] || self;
|
||||
self.log(widget.element_id , widget);
|
||||
window.w = widget;
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -841,9 +843,12 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({
|
||||
this.value = value;
|
||||
this.invalid = false;
|
||||
this.update_dom();
|
||||
this.on_value_changed();
|
||||
},
|
||||
set_value_from_ui: function() {
|
||||
this.value = undefined;
|
||||
this.on_value_changed();
|
||||
},
|
||||
on_value_changed: function() {
|
||||
},
|
||||
get_value: function() {
|
||||
return this.value;
|
||||
@@ -942,6 +947,7 @@ openerp.base.form.FieldChar = openerp.base.form.Field.extend({
|
||||
},
|
||||
set_value_from_ui: function() {
|
||||
this.value = this.$element.find('input').val();
|
||||
this._super();
|
||||
},
|
||||
validate: function() {
|
||||
this.invalid = false;
|
||||
@@ -1016,6 +1022,7 @@ openerp.base.form.FieldFloat = openerp.base.form.FieldChar.extend({
|
||||
},
|
||||
set_value_from_ui: function() {
|
||||
this.value = Number(this.$element.find('input').val().replace(/,/g, '.'));
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1036,6 +1043,7 @@ openerp.base.form.FieldInteger = openerp.base.form.FieldFloat.extend({
|
||||
},
|
||||
set_value_from_ui: function() {
|
||||
this.value = Number(this.$element.find('input').val());
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1073,6 +1081,7 @@ openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({
|
||||
if (this.value) {
|
||||
this.value = this.format(this.value);
|
||||
}
|
||||
this._super();
|
||||
},
|
||||
update_dom: function() {
|
||||
this._super.apply(this, arguments);
|
||||
@@ -1092,8 +1101,8 @@ openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({
|
||||
focus: function() {
|
||||
this.$element.find('input').focus();
|
||||
},
|
||||
parse: openerp.base.parse_datetime,
|
||||
format: openerp.base.format_datetime
|
||||
parse: openerp.base.str_to_datetime,
|
||||
format: openerp.base.datetime_to_str
|
||||
});
|
||||
|
||||
openerp.base.form.FieldDate = openerp.base.form.FieldDatetime.extend({
|
||||
@@ -1102,8 +1111,8 @@ openerp.base.form.FieldDate = openerp.base.form.FieldDatetime.extend({
|
||||
this.jqueryui_object = 'datepicker';
|
||||
this.validation_regex = /^\d+-\d+-\d+$/;
|
||||
},
|
||||
parse: openerp.base.parse_date,
|
||||
format: openerp.base.format_date
|
||||
parse: openerp.base.str_to_date,
|
||||
format: openerp.base.date_to_str
|
||||
});
|
||||
|
||||
openerp.base.form.FieldFloatTime = openerp.base.form.FieldChar.extend({
|
||||
@@ -1124,6 +1133,7 @@ openerp.base.form.FieldFloatTime = openerp.base.form.FieldChar.extend({
|
||||
set_value_from_ui: function() {
|
||||
var time = this.$element.find('input').val().split(':');
|
||||
this.set_value(parseInt(time[0], 10) + parseInt(time[1], 10) / 60);
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1148,6 +1158,7 @@ openerp.base.form.FieldText = openerp.base.form.Field.extend({
|
||||
},
|
||||
set_value_from_ui: function() {
|
||||
this.value = this.$element.find('textarea').val();
|
||||
this._super();
|
||||
},
|
||||
validate: function() {
|
||||
this.invalid = false;
|
||||
@@ -1183,6 +1194,7 @@ openerp.base.form.FieldBoolean = openerp.base.form.Field.extend({
|
||||
},
|
||||
set_value_from_ui: function() {
|
||||
this.value = this.$element.find('input').is(':checked');
|
||||
this._super();
|
||||
},
|
||||
update_dom: function() {
|
||||
this._super.apply(this, arguments);
|
||||
@@ -1265,6 +1277,7 @@ openerp.base.form.FieldSelection = openerp.base.form.Field.extend({
|
||||
var ikey = this.$element.find('select').val();
|
||||
var option = _.detect(this.field_index, function(x) {return x.ikey === ikey;});
|
||||
this.value = option === undefined ? false : option.ekey;
|
||||
this._super();
|
||||
},
|
||||
update_dom: function() {
|
||||
this._super.apply(this, arguments);
|
||||
@@ -1529,7 +1542,6 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
this.on_ui_change();
|
||||
}
|
||||
},
|
||||
set_value_from_ui: function() {},
|
||||
set_value: function(value) {
|
||||
value = value || null;
|
||||
var self = this;
|
||||
@@ -1697,7 +1709,6 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
});
|
||||
}
|
||||
},
|
||||
set_value_from_ui: function() {},
|
||||
set_value: function(value) {
|
||||
value = value || [];
|
||||
var self = this;
|
||||
@@ -1918,7 +1929,6 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
||||
get_value: function() {
|
||||
return [commands.replace_with(this.dataset.ids)];
|
||||
},
|
||||
set_value_from_ui: function() {},
|
||||
validate: function() {
|
||||
this.invalid = false;
|
||||
// TODO niv
|
||||
@@ -2192,10 +2202,67 @@ openerp.base.form.FormOpenPopup = openerp.base.OldWidget.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldReference = openerp.base.form.FieldChar.extend({
|
||||
openerp.base.form.FieldReference = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
//this.template = "FieldReference";
|
||||
this.template = "FieldReference";
|
||||
this.fields_view = {
|
||||
fields: {
|
||||
selection: {
|
||||
selection: view.fields_view.fields[this.name].selection
|
||||
},
|
||||
m2o: {
|
||||
relation: null
|
||||
}
|
||||
}
|
||||
}
|
||||
this.get_fields_values = view.get_fields_values;
|
||||
this.do_onchange = this.on_form_changed = this.on_nop;
|
||||
this.widgets = {};
|
||||
this.fields = {};
|
||||
this.selection = new openerp.base.form.FieldSelection(this, { attrs: {
|
||||
name: 'selection',
|
||||
widget: 'selection'
|
||||
}});
|
||||
this.selection.on_value_changed.add_last(this.on_selection_changed);
|
||||
this.m2o = new openerp.base.form.FieldMany2One(this, { attrs: {
|
||||
name: 'm2o',
|
||||
widget: 'many2one'
|
||||
}});
|
||||
},
|
||||
on_nop: function() {
|
||||
},
|
||||
on_selection_changed: function() {
|
||||
this.m2o.field.relation = this.selection.get_value();
|
||||
this.m2o.set_value(null);
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
this.selection.start();
|
||||
this.m2o.start();
|
||||
},
|
||||
is_valid: function() {
|
||||
return this.required === false || typeof(this.get_value()) === 'string';
|
||||
},
|
||||
is_dirty: function() {
|
||||
return this.selection.is_dirty() || this.m2o.is_dirty();
|
||||
},
|
||||
set_value: function(value) {
|
||||
this._super(value);
|
||||
if (typeof(value) === 'string') {
|
||||
var vals = value.split(',');
|
||||
this.selection.set_value(vals[0]);
|
||||
this.m2o.set_value(parseInt(vals[1], 10));
|
||||
}
|
||||
},
|
||||
get_value: function() {
|
||||
var model = this.selection.get_value(),
|
||||
id = this.m2o.get_value();
|
||||
if (typeof(model) === 'string' && typeof(id) === 'number') {
|
||||
return model + ',' + id;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2211,8 +2278,6 @@ openerp.base.form.FieldBinary = openerp.base.form.Field.extend({
|
||||
this.$element.find('button.oe-binary-file-save').click(this.on_save_as);
|
||||
this.$element.find('.oe-binary-file-clear').click(this.on_clear);
|
||||
},
|
||||
set_value_from_ui: function() {
|
||||
},
|
||||
update_dom: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$element.find('.oe-binary').toggle(!this.readonly);
|
||||
|
||||
@@ -1,140 +1,6 @@
|
||||
|
||||
openerp.base.formats = function(openerp) {
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
*
|
||||
* The timezone is assumed to be UTC (standard for OpenERP 6.1)
|
||||
* and will be converted to the browser's timezone.
|
||||
*
|
||||
* @param {String} str A string representing a datetime.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_datetime = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
var obj = Date.parse(str + " GMT");
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid datetime";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* date string format (exemple: '2011-12-01').
|
||||
*
|
||||
* @param {String} str A string representing a date.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_date = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d\d\d-\d\d-\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid date";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a string to a Date javascript object using OpenERP's
|
||||
* time string format (exemple: '15:12:35').
|
||||
*
|
||||
* @param {String} str A string representing a time.
|
||||
* @returns {Date}
|
||||
*/
|
||||
openerp.base.parse_time = function(str) {
|
||||
if(!str) {
|
||||
return str;
|
||||
}
|
||||
var regex = /\d\d:\d\d:\d\d/;
|
||||
var res = regex.exec(str);
|
||||
if ( res[0] != str ) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
var obj = Date.parse(str);
|
||||
if (! obj) {
|
||||
throw "'" + str + "' is not a valid time";
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/*
|
||||
* Left-pad provided arg 1 with zeroes until reaching size provided by second
|
||||
* argument.
|
||||
*
|
||||
* @param {Number|String} str value to pad
|
||||
* @param {Number} size size to reach on the final padded value
|
||||
* @returns {String} padded string
|
||||
*/
|
||||
var zpad = function(str, size) {
|
||||
str = "" + str;
|
||||
return new Array(size - str.length + 1).join('0') + str;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
*
|
||||
* The timezone of the Date object is assumed to be the one of the
|
||||
* browser and it will be converted to UTC (standard for OpenERP 6.1).
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a datetime.
|
||||
*/
|
||||
openerp.base.format_datetime = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getUTCFullYear(),4) + "-" + zpad(obj.getUTCMonth() + 1,2) + "-"
|
||||
+ zpad(obj.getUTCDate(),2) + " " + zpad(obj.getUTCHours(),2) + ":"
|
||||
+ zpad(obj.getUTCMinutes(),2) + ":" + zpad(obj.getUTCSeconds(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* date string format (exemple: '2011-12-01').
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a date.
|
||||
*/
|
||||
openerp.base.format_date = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getFullYear(),4) + "-" + zpad(obj.getMonth() + 1,2) + "-"
|
||||
+ zpad(obj.getDate(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Date javascript object to a string using OpenERP's
|
||||
* time string format (exemple: '15:12:35').
|
||||
*
|
||||
* @param {Date} obj
|
||||
* @returns {String} A string representing a time.
|
||||
*/
|
||||
openerp.base.format_time = function(obj) {
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
return zpad(obj.getHours(),2) + ":" + zpad(obj.getMinutes(),2) + ":"
|
||||
+ zpad(obj.getSeconds(),2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a single atomic value based on a field descriptor
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @namespace handles editability case for lists, because it depends on form and forms already depends on lists it had to be split out
|
||||
*/
|
||||
openerp.base.list.editable = function (openerp) {
|
||||
openerp.base.list_editable = function (openerp) {
|
||||
var KEY_RETURN = 13,
|
||||
KEY_ESCAPE = 27;
|
||||
|
||||
|
||||
@@ -482,7 +482,8 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
*/
|
||||
do_activate_record: function (index, id, dataset) {
|
||||
var self = this;
|
||||
this.dataset.read_slice({
|
||||
// TODO is it needed ?
|
||||
this.dataset.read_slice([],{
|
||||
context: dataset.get_context(),
|
||||
domain: dataset.get_domain()
|
||||
}, function () {
|
||||
@@ -1039,11 +1040,9 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas
|
||||
d = new $.Deferred(),
|
||||
page = this.datagroup.openable ? this.page : view.page;
|
||||
|
||||
dataset.read_slice({
|
||||
fields: _.pluck(_.select(this.columns, function(x) {return x.tag == "field"}), 'name'),
|
||||
offset: page * limit,
|
||||
limit: limit
|
||||
}, function (records) {
|
||||
var fields = _.pluck(_.select(this.columns, function(x) {return x.tag == "field"}), 'name');
|
||||
var options = { offset: page * limit, limit: limit };
|
||||
dataset.read_slice(fields, options , function (records) {
|
||||
if (!self.datagroup.openable) {
|
||||
view.configure_pager(dataset);
|
||||
} else {
|
||||
|
||||
@@ -72,7 +72,7 @@ openerp.base.TreeView = openerp.base.View.extend({
|
||||
'toolbar': has_toolbar
|
||||
}));
|
||||
|
||||
this.dataset.read_slice({fields: this.fields_list()}, function (records) {
|
||||
this.dataset.read_slice(this.fields_list(), {}, function (records) {
|
||||
if (!has_toolbar) {
|
||||
// WARNING: will do a second read on the same ids, but only on
|
||||
// first load so not very important
|
||||
|
||||
@@ -17,6 +17,7 @@ openerp.base.ActionManager = openerp.base.Widget.extend({
|
||||
this.dialog = null;
|
||||
this.dialog_viewmanager = null;
|
||||
this.client_widget = null;
|
||||
this.url = {}
|
||||
},
|
||||
render: function() {
|
||||
return "<div id='"+this.element_id+"'></div>";
|
||||
@@ -29,11 +30,37 @@ openerp.base.ActionManager = openerp.base.Widget.extend({
|
||||
this.dialog = null;
|
||||
}
|
||||
},
|
||||
inner_stop: function () {
|
||||
content_stop: function () {
|
||||
if (this.inner_viewmanager) {
|
||||
this.inner_viewmanager.stop();
|
||||
this.inner_viewmanager = null;
|
||||
}
|
||||
if (this.client_widget) {
|
||||
this.client_widget.stop();
|
||||
this.client_widget = null;
|
||||
}
|
||||
},
|
||||
url_update: function(action) {
|
||||
// this.url = {
|
||||
// "model": action.model,
|
||||
// "domain": action.domain,
|
||||
// };
|
||||
// action.res_model
|
||||
// action.domain
|
||||
// action.context
|
||||
// after
|
||||
// action.views
|
||||
// action.res_id
|
||||
// mode
|
||||
// menu
|
||||
},
|
||||
url_stringify: function(action) {
|
||||
},
|
||||
url_parse: function(action) {
|
||||
},
|
||||
on_url_update: function(url) {
|
||||
},
|
||||
do_url_action: function(url) {
|
||||
},
|
||||
do_action: function(action, on_close) {
|
||||
var type = action.type.replace(/\./g,'_');
|
||||
@@ -66,9 +93,10 @@ openerp.base.ActionManager = openerp.base.Widget.extend({
|
||||
this.dialog.open();
|
||||
} else {
|
||||
this.dialog_stop();
|
||||
this.inner_stop();
|
||||
this.content_stop();
|
||||
this.inner_viewmanager = new openerp.base.ViewManagerAction(this, action);
|
||||
this.inner_viewmanager.appendTo(this.$element);
|
||||
this.url_update(action);
|
||||
}
|
||||
/* new window code
|
||||
this.rpc("/base/session/save_session_action", { the_action : action}, function(key) {
|
||||
@@ -90,8 +118,9 @@ openerp.base.ActionManager = openerp.base.Widget.extend({
|
||||
});
|
||||
},
|
||||
ir_actions_client: function (action) {
|
||||
this.client_widget = openerp.base.client_actions.get_object(action.tag);
|
||||
new this.client_widget(this, this.element_id, action.params).start();
|
||||
this.content_stop();
|
||||
var ClientWidget = openerp.base.client_actions.get_object(action.tag);
|
||||
(this.client_widget = new ClientWidget(this, action.params)).appendTo(this);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<li id="back-to-login">Back to Login</li>
|
||||
</ul>
|
||||
</t>
|
||||
<t t-name="CreateDB">
|
||||
<t t-name="Database.CreateDB">
|
||||
<form name="create_db_form" class="oe_forms" method="POST">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
@@ -79,8 +79,7 @@
|
||||
<table align="center" class="db_option_table">
|
||||
<tr>
|
||||
<td><label for="super_admin_pwd">Master password:</label></td>
|
||||
<td><input type="password" name="super_admin_pwd"
|
||||
class="required" autofocus="autofocus"/></td>
|
||||
<td><input type="password" name="super_admin_pwd" class="required" value="admin"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="db_name">New database name:</label></td>
|
||||
@@ -95,9 +94,7 @@
|
||||
<td>
|
||||
<select name="db_lang" t-if="lang_list">
|
||||
<t t-foreach="lang_list" t-as="lang">
|
||||
<option t-att-value="lang[0]"
|
||||
t-att-selected="lang[0] === 'en_US' ? 'selected' : undefined">
|
||||
<t t-esc="lang[1]"/></option>
|
||||
<option t-att-value="lang[0]" t-att-selected="lang[0] === 'en_US' ? 'selected' : undefined"><t t-esc="lang[1]"/></option>
|
||||
</t>
|
||||
</select>
|
||||
</td>
|
||||
@@ -367,7 +364,6 @@
|
||||
t-att-data-shortcut-id="shortcut.id"
|
||||
><t t-esc="shortcut.name"/></li>
|
||||
</ul>
|
||||
|
||||
<t t-name="Menu">
|
||||
<table align="center">
|
||||
<tr>
|
||||
@@ -788,7 +784,16 @@
|
||||
<div t-att-id="widget.list_id"></div>
|
||||
</t>
|
||||
<t t-name="FieldReference">
|
||||
<input type="text" t-att-name="widget.name" t-att-id="widget.element_id" t-att-class="'field_' + widget.type" style="width: 100%" placeholder="Widget Reference"/>
|
||||
<table border="0" width="100%" cellpadding="0" cellspacing="0" class="oe_frame oe_forms">
|
||||
<tr>
|
||||
<td t-att-id="widget.selection.element_id" class="oe_form_frame_cell oe_form_selection">
|
||||
<t t-raw="widget.selection.render()"/>
|
||||
</td>
|
||||
<td t-att-id="widget.m2o.element_id" class="oe_form_frame_cell oe_form_many2one" nowrap="true">
|
||||
<t t-raw="widget.m2o.render()"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
<t t-name="FieldBoolean">
|
||||
<input type="checkbox"
|
||||
@@ -1170,7 +1175,6 @@
|
||||
<t t-name="ExportView">
|
||||
<a id="exportview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Export</a>
|
||||
</t>
|
||||
|
||||
<t t-name="ExportTreeView">
|
||||
<table class="view" style="background-color: #F3F3F3;">
|
||||
<tr>
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"POT-Creation-Date: 2011-08-17 13:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,3 +17,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
||||
#: addons/base_calendar/static/src/xml/base_calendar.xml:0
|
||||
msgid " "
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
'#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f',
|
||||
'#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00',
|
||||
'#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#ffc900' ];
|
||||
this.color_map = {};
|
||||
},
|
||||
start: function() {
|
||||
this.rpc("/base_calendar/calendarview/load", {"model": this.model, "view_id": this.view_id, 'toolbar': true}, this.on_loaded);
|
||||
@@ -136,17 +137,21 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
reload_event: function(id) {
|
||||
this.dataset.read_ids([id], _.keys(this.fields), this.on_events_loaded);
|
||||
},
|
||||
get_color: function(index) {
|
||||
index = index % this.COLOR_PALETTE.length;
|
||||
return this.COLOR_PALETTE[index];
|
||||
get_color: function(key) {
|
||||
if (this.color_map[key]) {
|
||||
return this.color_map[key];
|
||||
}
|
||||
var index = _.keys(this.color_map).length % this.COLOR_PALETTE.length;
|
||||
var color = this.COLOR_PALETTE[index];
|
||||
this.color_map[key] = color;
|
||||
return color;
|
||||
},
|
||||
on_events_loaded: function(events, fn_filter, no_filter_reload) {
|
||||
var self = this;
|
||||
|
||||
//To parse Events we have to convert date Format
|
||||
var res_events = [],
|
||||
sidebar_items = [],
|
||||
sidebar_ids = [];
|
||||
sidebar_items = {};
|
||||
for (var e = 0; e < events.length; e++) {
|
||||
var evt = events[e];
|
||||
if (!evt[this.date_start]) {
|
||||
@@ -157,30 +162,28 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
if (this.color_field) {
|
||||
var filter = evt[this.color_field];
|
||||
if (filter) {
|
||||
var filter_item = {
|
||||
value: (typeof filter === 'object') ? filter[0] : filter,
|
||||
label: (typeof filter === 'object') ? filter[1] : filter
|
||||
}
|
||||
if (typeof(fn_filter) === 'function' && !fn_filter(filter_item.value)) {
|
||||
var filter_value = (typeof filter === 'object') ? filter[0] : filter;
|
||||
if (typeof(fn_filter) === 'function' && !fn_filter(filter_value)) {
|
||||
continue;
|
||||
}
|
||||
var filter_index = _.indexOf(sidebar_ids, filter_item.value);
|
||||
if (filter_index === -1) {
|
||||
evt.color = filter_item.color = this.get_color(sidebar_ids.length);
|
||||
sidebar_items.push(filter_item);
|
||||
sidebar_ids.push(filter_item.value);
|
||||
} else {
|
||||
evt.color = this.get_color(filter_index);
|
||||
var filter_item = {
|
||||
value: filter_value,
|
||||
label: (typeof filter === 'object') ? filter[1] : filter,
|
||||
color: this.get_color(filter_value)
|
||||
}
|
||||
if (!sidebar_items[filter_value]) {
|
||||
sidebar_items[filter_value] = filter_item;
|
||||
}
|
||||
evt.color = filter_item.color;
|
||||
evt.textColor = '#ffffff';
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fields[this.date_start]['type'] == 'date') {
|
||||
evt[this.date_start] = openerp.base.parse_date(evt[this.date_start]).set({hour: 9}).toString('yyyy-MM-dd HH:mm:ss');
|
||||
evt[this.date_start] = openerp.base.str_to_date(evt[this.date_start]).set({hour: 9}).toString('yyyy-MM-dd HH:mm:ss');
|
||||
}
|
||||
if (this.date_stop && evt[this.date_stop] && this.fields[this.date_stop]['type'] == 'date') {
|
||||
evt[this.date_stop] = openerp.base.parse_date(evt[this.date_stop]).set({hour: 17}).toString('yyyy-MM-dd HH:mm:ss');
|
||||
evt[this.date_stop] = openerp.base.str_to_date(evt[this.date_stop]).set({hour: 17}).toString('yyyy-MM-dd HH:mm:ss');
|
||||
}
|
||||
res_events.push(this.convert_event(evt));
|
||||
}
|
||||
@@ -192,8 +195,8 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
}
|
||||
},
|
||||
convert_event: function(evt) {
|
||||
var date_start = openerp.base.parse_datetime(evt[this.date_start]),
|
||||
date_stop = this.date_stop ? openerp.base.parse_datetime(evt[this.date_stop]) : null,
|
||||
var date_start = openerp.base.str_to_datetime(evt[this.date_start]),
|
||||
date_stop = this.date_stop ? openerp.base.str_to_datetime(evt[this.date_stop]) : null,
|
||||
date_delay = evt[this.date_delay] || null,
|
||||
res_text = '',
|
||||
res_description = [];
|
||||
@@ -277,9 +280,9 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
var data = {
|
||||
name: event_obj.text
|
||||
};
|
||||
data[this.date_start] = openerp.base.format_datetime(event_obj.start_date);
|
||||
data[this.date_start] = openerp.base.datetime_to_str(event_obj.start_date);
|
||||
if (this.date_stop) {
|
||||
data[this.date_stop] = openerp.base.format_datetime(event_obj.end_date);
|
||||
data[this.date_stop] = openerp.base.datetime_to_str(event_obj.end_date);
|
||||
}
|
||||
if (this.date_delay) {
|
||||
var diff_seconds = Math.round((event_obj.end_date.getTime() - event_obj.start_date.getTime()) / 1000);
|
||||
@@ -299,8 +302,7 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
// TODO: handle non-empty results.group_by with read_group
|
||||
self.dataset.context = self.context = results.context;
|
||||
self.dataset.domain = self.domain = results.domain;
|
||||
self.dataset.read_slice({
|
||||
fields: _.keys(self.fields),
|
||||
self.dataset.read_slice(_.keys(self.fields), {
|
||||
offset:0,
|
||||
limit: self.limit
|
||||
}, function(events) {
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="CalendarView.sidebar.responsible">
|
||||
<div t-foreach="filters" t-as="filter" class="oe_calendar_responsible" t-attf-style="background: #{filter.color}">
|
||||
<input type="checkbox" name="selection" t-att-value="filter.value"/>
|
||||
<span><t t-esc="filter.label"/></span>
|
||||
<div t-foreach="filters" class="oe_calendar_responsible" t-attf-style="background: #{filters_value.color}">
|
||||
<input type="checkbox" name="selection" t-att-value="filters_value.value"/>
|
||||
<span><t t-esc="filters_value.label"/></span>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"POT-Creation-Date: 2011-08-17 13:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,3 +17,31 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
||||
#: addons/base_dashboard/static/src/xml/base_dashboard.xml:0
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base_dashboard/static/src/xml/base_dashboard.xml:0
|
||||
msgid "Undo"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base_dashboard/static/src/xml/base_dashboard.xml:0
|
||||
msgid "Add Widget"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base_dashboard/static/src/xml/base_dashboard.xml:0
|
||||
msgid "Change layout"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base_dashboard/static/src/xml/base_dashboard.xml:0
|
||||
msgid "Choose dashboard layout"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base_dashboard/static/src/xml/base_dashboard.xml:0
|
||||
msgid "progress:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base_dashboard/static/src/xml/base_dashboard.xml:0
|
||||
msgid "%"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
||||
this._super(view, node);
|
||||
this.template = 'DashBoard';
|
||||
this.actions_attrs = {};
|
||||
this.action_managers = [];
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
@@ -23,8 +24,9 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
||||
this.$element.find('.oe-dashboard-link-reset').click(this.on_reset);
|
||||
this.$element.find('.oe-dashboard-link-add_widget').click(this.on_add_widget);
|
||||
this.$element.find('.oe-dashboard-link-change_layout').click(this.on_change_layout);
|
||||
this.$element.find('.oe-dashboard-column .oe-dashboard-fold').click(this.on_fold_action);
|
||||
this.$element.find('.oe-dashboard-column .ui-icon-closethick').click(this.on_close_action);
|
||||
|
||||
this.$element.delegate('.oe-dashboard-column .oe-dashboard-fold', 'click', this.on_fold_action);
|
||||
this.$element.delegate('.oe-dashboard-column .ui-icon-closethick', 'click', this.on_close_action);
|
||||
|
||||
this.actions_attrs = {};
|
||||
// Init actions
|
||||
@@ -58,7 +60,23 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
||||
},
|
||||
on_add_widget: function() {
|
||||
var self = this;
|
||||
var action = {
|
||||
var action_manager = new openerp.base.ActionManager(this);
|
||||
var dialog = new openerp.base.Dialog(this, {
|
||||
title : 'Actions',
|
||||
width: 800,
|
||||
height: 600,
|
||||
buttons : {
|
||||
Cancel : function() {
|
||||
$(this).dialog('destroy');
|
||||
},
|
||||
Add : function() {
|
||||
self.do_add_widget(action_manager.inner_viewmanager.views.list.controller);
|
||||
$(this).dialog('destroy');
|
||||
}
|
||||
}
|
||||
}).start().open();
|
||||
action_manager.appendTo(dialog.$element);
|
||||
action_manager.do_action({
|
||||
res_model : 'ir.actions.actions',
|
||||
views : [[false, 'list']],
|
||||
type : 'ir.actions.act_window',
|
||||
@@ -69,33 +87,12 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
||||
views_switcher : false,
|
||||
action_buttons : false
|
||||
}
|
||||
};
|
||||
// TODO: create a Dialog controller which optionally takes an action
|
||||
// Should set width & height automatically and take buttons & views callback
|
||||
var dialog_id = _.uniqueId('act_window_dialog');
|
||||
var action_manager = new openerp.base.ActionManager(this, dialog_id);
|
||||
$('<div id=' + dialog_id + '>').dialog({
|
||||
modal : true,
|
||||
title : 'Actions',
|
||||
width : 800,
|
||||
height : 600,
|
||||
buttons : {
|
||||
Cancel : function() {
|
||||
$(this).dialog('destroy');
|
||||
},
|
||||
Add : function() {
|
||||
self.do_add_widget(action_manager);
|
||||
$(this).dialog('destroy');
|
||||
}
|
||||
}
|
||||
});
|
||||
action_manager.start();
|
||||
action_manager.do_action(action);
|
||||
// TODO: should bind ListView#select_record in order to catch record clicking
|
||||
},
|
||||
do_add_widget : function(action_manager) {
|
||||
do_add_widget : function(listview) {
|
||||
var self = this,
|
||||
actions = action_manager.viewmanager.views.list.controller.groups.get_selection().ids,
|
||||
actions = listview.groups.get_selection().ids,
|
||||
results = [],
|
||||
qdict = { view : this.view };
|
||||
// TODO: should load multiple actions at once
|
||||
@@ -229,6 +226,7 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
||||
pager: false
|
||||
};
|
||||
var am = new openerp.base.ActionManager(this);
|
||||
this.action_managers.push(am);
|
||||
am.appendTo($("#"+this.view.element_id + '_action_' + action.id));
|
||||
am.do_action(action);
|
||||
},
|
||||
@@ -244,8 +242,12 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
||||
return QWeb.render(this.template, this);
|
||||
},
|
||||
do_reload: function() {
|
||||
this.view.widget_parent.stop();
|
||||
this.view.widget_parent.start();
|
||||
_.each(this.action_managers, function(am) {
|
||||
am.stop();
|
||||
});
|
||||
this.action_managers = [];
|
||||
this.view.stop();
|
||||
this.view.start();
|
||||
}
|
||||
});
|
||||
openerp.base.form.DashBoardLegacy = openerp.base.form.DashBoard.extend({
|
||||
@@ -290,7 +292,7 @@ openerp.base_dashboard.ConfigOverview = openerp.base.View.extend({
|
||||
this.dataset.domain = [['type', '=', 'manual']];
|
||||
},
|
||||
start: function () {
|
||||
$.when(this.dataset.read_slice({fields: ['state', 'action_id', 'category_id']}),
|
||||
$.when(this.dataset.read_slice(['state', 'action_id', 'category_id']),
|
||||
this.dataset.call('progress'))
|
||||
.then(this.on_records_loaded);
|
||||
},
|
||||
@@ -345,16 +347,11 @@ openerp.base_dashboard.ConfigOverview = openerp.base.View.extend({
|
||||
openerp.base.client_actions.add(
|
||||
'board.home.applications', 'openerp.base_dashboard.ApplicationTiles');
|
||||
openerp.base_dashboard.ApplicationTiles = openerp.base.View.extend({
|
||||
init: function (parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.dataset = new openerp.base.DataSetSearch(
|
||||
this, 'ir.ui.menu', null, [['parent_id', '=', false]]);
|
||||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
this.dataset.read_slice(
|
||||
{fields: ['name', 'web_icon_data', 'web_icon_hover_data']},
|
||||
function (applications) {
|
||||
return new openerp.base.DataSetSearch(
|
||||
this, 'ir.ui.menu', null, [['parent_id', '=', false]])
|
||||
.read_slice( ['name', 'web_icon_data', 'web_icon_hover_data'], {}, function (applications) {
|
||||
// Create a matrix of 3*x applications
|
||||
var rows = [];
|
||||
while (applications.length) {
|
||||
@@ -369,24 +366,18 @@ openerp.base_dashboard.ApplicationTiles = openerp.base.View.extend({
|
||||
$this.closest('.openerp')
|
||||
.find('.menu a[data-menu=' + $this.data('menuid') + ']')
|
||||
.click();});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
openerp.base.client_actions.add(
|
||||
'board.home.widgets', 'openerp.base_dashboard.Widgets');
|
||||
openerp.base_dashboard.Widgets = openerp.base.View.extend({
|
||||
init: function (parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.user_widgets = new openerp.base.DataSetSearch(
|
||||
start: function () {
|
||||
return new openerp.base.DataSetSearch(
|
||||
this, 'res.widget.user', null,
|
||||
['|', ['user_id', '=', false],
|
||||
['user_id', '=', parseInt(this.session.uid, 10)]]);
|
||||
this.widgets = new openerp.base.DataSetSearch(this, 'res.widget');
|
||||
},
|
||||
start: function () {
|
||||
this.user_widgets.read_slice(
|
||||
{fields: ['widget_id', 'user_id']},
|
||||
this.on_widgets_list_loaded);
|
||||
['user_id', '=', parseInt(this.session.uid, 10)]])
|
||||
.read_slice(['widget_id', 'user_id'], {}, this.on_widgets_list_loaded);
|
||||
},
|
||||
on_widgets_list_loaded: function (user_widgets) {
|
||||
var self = this;
|
||||
@@ -398,18 +389,19 @@ openerp.base_dashboard.Widgets = openerp.base.View.extend({
|
||||
user_widget_id: widget['id']
|
||||
};
|
||||
});
|
||||
this.widgets.read_ids(_(user_widgets).pluck('widget_id'), ['title'], function (widgets) {
|
||||
_(widgets).each(function (widget) {
|
||||
_.extend(widget, widget_user[widget['id']]);
|
||||
new openerp.base.DataSetSearch(this, 'res.widget')
|
||||
.read_ids(_(user_widgets).pluck('widget_id'), ['title'], function (widgets) {
|
||||
_(widgets).each(function (widget) {
|
||||
_.extend(widget, widget_user[widget['id']]);
|
||||
});
|
||||
var url = _.sprintf(
|
||||
'/base_dashboard/widgets/content?session_id=%s&widget_id=',
|
||||
self.session.session_id);
|
||||
self.$element.html(QWeb.render('HomeWidgets', {
|
||||
widgets: widgets,
|
||||
url: url
|
||||
}));
|
||||
});
|
||||
var url = _.sprintf(
|
||||
'/base_dashboard/widgets/content?session_id=%s&widget_id=',
|
||||
self.session.session_id);
|
||||
self.$element.html(QWeb.render('HomeWidgets', {
|
||||
widgets: widgets,
|
||||
url: url
|
||||
}));
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"POT-Creation-Date: 2011-08-17 13:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,3 +17,25 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
||||
#: addons/base_default_home/static/src/xml/base_default_home.xml:0
|
||||
msgid "Welcome to OpenERP"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base_default_home/static/src/xml/base_default_home.xml:0
|
||||
msgid ""
|
||||
"Don't forget to bookmark your application address to come back\n"
|
||||
" later:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base_default_home/static/src/xml/base_default_home.xml:0
|
||||
msgid "URL:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base_default_home/static/src/xml/base_default_home.xml:0
|
||||
msgid "login:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/base_default_home/static/src/xml/base_default_home.xml:0
|
||||
msgid "Install"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
.oe-static-home {
|
||||
padding: 0.5em 0.5em;
|
||||
text-align: center;
|
||||
}
|
||||
.oe-static-home h1 {
|
||||
margin: 0 0 0.3em
|
||||
}
|
||||
.oe-static-home-banner {
|
||||
display: inline-block;
|
||||
margin: 0.5em 0;
|
||||
margin: auto 0;
|
||||
padding: 0.5em 5em;
|
||||
border: 1px inset #808080;
|
||||
background-color: #e6e3e3;
|
||||
-moz-border-radius: 2em;
|
||||
-webkit-border-radius: 2em;
|
||||
border-radius: 2em;
|
||||
text-align: left;
|
||||
}
|
||||
.oe-static-home-banner h1 {
|
||||
margin: 0 0 0.3em
|
||||
.oe-static-home-banner li {
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
}
|
||||
.oe-static-home-banner p {
|
||||
|
||||
}
|
||||
.oe-static-home-banner address {
|
||||
.oe-static-home address {
|
||||
font-style: normal;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
@@ -63,30 +63,44 @@ openerp.base_default_home = function (openerp) {
|
||||
if (!_(installed_modules).isEmpty()) {
|
||||
return old_home.call(self);
|
||||
}
|
||||
self.$element.find('.oe-application').html(
|
||||
QWeb.render('StaticHome', {
|
||||
url: window.location.protocol + '//' + window.location.host + window.location.pathname,
|
||||
session: self.session,
|
||||
rows: openerp.base_default_home.applications
|
||||
})).delegate('.oe-static-home-tile-text button', 'click', function () {
|
||||
self.install_module($(this).val());
|
||||
self.action_manager.do_action({
|
||||
type: 'ir.actions.client',
|
||||
tag: 'home.default'
|
||||
})
|
||||
|
||||
}, function (err, event) {
|
||||
event.preventDefault();
|
||||
return old_home.call(self);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.client_actions.add(
|
||||
'home.default', 'openerp.base_default_home.DefaultHome');
|
||||
openerp.base_default_home.DefaultHome = openerp.base.View.extend({
|
||||
template: 'StaticHome',
|
||||
start: function () {
|
||||
var r = this._super(), self = this;
|
||||
this.$element.delegate('.oe-static-home-tile-text button', 'click', function () {
|
||||
self.install_module($(this).val());
|
||||
});
|
||||
return r;
|
||||
},
|
||||
render: function () {
|
||||
return this._super({
|
||||
url: window.location.protocol + '//' + window.location.host + window.location.pathname,
|
||||
session: this.session,
|
||||
rows: openerp.base_default_home.applications
|
||||
})
|
||||
},
|
||||
install_module: function (module_name) {
|
||||
var Modules = new openerp.base.DataSetSearch(
|
||||
this, 'ir.module.module', null,
|
||||
[['name', '=', module_name], ['state', '=', 'uninstalled']]),
|
||||
Upgrade = new openerp.base.DataSet(this, 'base.module.upgrade');
|
||||
this, 'ir.module.module', null, [['name', '=', module_name], ['state', '=', 'uninstalled']]);
|
||||
var Upgrade = new openerp.base.DataSet(this, 'base.module.upgrade');
|
||||
|
||||
$.blockUI({
|
||||
message: '<img src="/base_default_home/static/src/img/throbber.gif">'
|
||||
});
|
||||
Modules.read_slice({fields: ['id']}, function (records) {
|
||||
Modules.read_slice(['id'], {}, function (records) {
|
||||
if (!(records.length === 1)) { return; }
|
||||
Modules.call('state_update',
|
||||
[_.pluck(records, 'id'), 'to install', ['uninstalled']],
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
<template>
|
||||
<div t-name="StaticHome" class="oe-static-home">
|
||||
<h1>Welcome to your new OpenERP instance.</h1>
|
||||
<div class="oe-static-home-banner">
|
||||
<h1>Welcome to OpenERP</h1>
|
||||
<p>
|
||||
Don't forget to bookmark your application address to come back
|
||||
later:
|
||||
</p>
|
||||
<address>
|
||||
URL: <a t-att-href="url"><t t-esc="url"/></a><br/>
|
||||
login: <t t-esc="session.login"/>
|
||||
</address>
|
||||
<li>Bookmark this <a t-att-href="url">page</a></li>
|
||||
<li>Remember your login: <i><t t-esc="session.login"/></i></li>
|
||||
<li>Choose the first OpenERP Application you want to install..</li>
|
||||
</div>
|
||||
|
||||
<div class="oe-static-home-tiles">
|
||||
<table width="100%">
|
||||
<tr t-foreach="rows" t-as="row">
|
||||
@@ -27,9 +21,7 @@
|
||||
<div class="oe-static-home-tile-text">
|
||||
<h2><t t-esc="application.name"/></h2>
|
||||
<p><t t-esc="application.help"/></p>
|
||||
<button type="button"
|
||||
t-att-value="application.module">
|
||||
Install</button>
|
||||
<button type="button" t-att-value="application.module"> Install</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"POT-Creation-Date: 2011-08-17 13:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"POT-Creation-Date: 2011-08-17 13:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
||||
@@ -79,7 +79,7 @@ init: function(parent, element_id, dataset, view_id) {
|
||||
get_events: function() {
|
||||
|
||||
var self = this;
|
||||
this.dataset.read_slice({}, function(result) {
|
||||
this.dataset.read_slice([],{}, function(result) {
|
||||
self.load_event(result);
|
||||
});
|
||||
|
||||
@@ -474,31 +474,31 @@ init: function(parent, element_id, dataset, view_id) {
|
||||
convert_str_date: function (str){
|
||||
if (str.length == 19){
|
||||
this.format = "yyyy-MM-dd HH:mm:ss";
|
||||
return openerp.base.parse_datetime(str);
|
||||
return openerp.base.str_to_datetime(str);
|
||||
} else if (str.length == 10){
|
||||
this.format = "yyyy-MM-dd";
|
||||
return openerp.base.parse_date(str);
|
||||
return openerp.base.str_to_date(str);
|
||||
} else if (str.length == 8){
|
||||
this.format = "HH:mm:ss";
|
||||
return openerp.base.parse_time(str);
|
||||
return openerp.base.str_to_time(str);
|
||||
}
|
||||
throw "Unrecognized date/time format";
|
||||
},
|
||||
|
||||
convert_date_str: function(full_date) {
|
||||
if (this.format == "yyyy-MM-dd HH:mm:ss"){
|
||||
return openerp.base.format_datetime(full_date);
|
||||
return openerp.base.datetime_to_str(full_date);
|
||||
} else if (this.format == "yyyy-MM-dd"){
|
||||
return openerp.base.format_date(full_date);
|
||||
return openerp.base.date_to_str(full_date);
|
||||
} else if (this.format == "HH:mm:ss"){
|
||||
return openerp.base.format_time(full_date);
|
||||
return openerp.base.time_to_str(full_date);
|
||||
}
|
||||
throw "Unrecognized date/time format";
|
||||
},
|
||||
|
||||
reload_gantt: function() {
|
||||
var self = this;
|
||||
this.dataset.read_slice({}, function(response) {
|
||||
this.dataset.read_slice([],{}, function(response) {
|
||||
ganttChartControl.clearAll();
|
||||
jQuery("#GanttDiv").children().remove();
|
||||
self.load_event(response);
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"POT-Creation-Date: 2011-08-17 13:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
||||
@@ -89,7 +89,7 @@ openerp.base_graph.GraphView = openerp.base.View.extend({
|
||||
}
|
||||
this.dataset.domain = domain;
|
||||
this.dataset.context = this.view_manager.dataset.context;
|
||||
this.dataset.read_slice({fields: _(this.fields).keys()}, function(res) {
|
||||
this.dataset.read_slice(_(this.fields).keys(),{}, function(res) {
|
||||
self.schedule_chart(res);
|
||||
});
|
||||
}
|
||||
@@ -468,7 +468,7 @@ openerp.base_graph.GraphView = openerp.base.View.extend({
|
||||
}
|
||||
self.dataset.context = results.context;
|
||||
self.dataset.domain = results.domain;
|
||||
self.dataset.read_slice({}, $.proxy(self, 'load_chart'));
|
||||
self.dataset.read_slice([],{}, $.proxy(self, 'load_chart'));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"POT-Creation-Date: 2011-08-17 13:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"POT-Creation-Date: 2011-08-17 13:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2011-08-16 15:47+0200\n"
|
||||
"POT-Creation-Date: 2011-08-17 13:28+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,3 +17,55 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 0.9.6\n"
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "OpenERP"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Home"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Database:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Choose Database..."
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Login:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Password:"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid ":"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Options"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:0
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ openerp.web_mobile.FormView = openerp.base.Widget.extend({
|
||||
view_id = this.action.views[1][0];
|
||||
|
||||
this.dataset = new openerp.base.DataSetSearch(this.session, this.action.res_model, null, null);
|
||||
this.dataset.read_slice({}, function (result) {
|
||||
this.dataset.read_slice([],{}, function (result) {
|
||||
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
if (result[i].id == id) {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name" : "OpenERP Web base",
|
||||
"version" : "2.0",
|
||||
"depends" : [],
|
||||
'active': False,
|
||||
'js' : [
|
||||
"../base/static/lib/datejs/date-en-US.js",
|
||||
"../base/static/lib/jquery/jquery-1.6.2.js",
|
||||
"../base/static/lib/json/json2.js",
|
||||
"../base/static/lib/qweb/qweb2.js",
|
||||
"../base/static/lib/underscore/underscore.js",
|
||||
"../base/static/lib/underscore/underscore.string.js",
|
||||
"../base/static/src/js/boot.js",
|
||||
"../base/static/src/js/core.js",
|
||||
"../base/static/src/js/formats.js",
|
||||
"../base/static/src/js/chrome.js",
|
||||
"../base/static/src/js/data.js",
|
||||
],
|
||||
'css' : [
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html style="height: 100%">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>OpenERP web_rpc example</title>
|
||||
<style type="text/css">
|
||||
pre.run {
|
||||
border: 1px solid black; margin:0;padding:4px;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" src="/base/webclient/js?mods=web_rpc"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$("#ex1but").bind("click",function(){
|
||||
eval($("#ex1").text());
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>OpenERP web_rpc examples</h1>
|
||||
<h2>Example 1: Display a list of defined ir.model <button id="ex1but">Run it !</button> </h2>
|
||||
<h3>Code: </h3>
|
||||
<pre>
|
||||
<script type="text/javascript" src="/base/webclient/js?mods=web_rpc"></script>
|
||||
<script type="text/javascript">
|
||||
<pre id="ex1" class="run">
|
||||
var c = openerp.init(); // get a new webclient
|
||||
c._modules_loaded = true; // Hack to prevent loading of additional modules
|
||||
|
||||
var s = new c.base.Session(); // setup a Session
|
||||
s.session_login("web-trunk", "admin", "admin", function() {
|
||||
|
||||
var ds = new c.base.DataSetSearch(s, "ir.model"); // DataSetSearch used to search, read
|
||||
ds.read_slice(['name','model'], {}, function(users){
|
||||
for(var i in users) {
|
||||
$("#ex1res").append("<li>" + users[i].model + " (" + users[i].name + ") </li>")
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
</pre></script>
|
||||
</pre>
|
||||
<h3>Div for output:</h3>
|
||||
<div id="ex1res" style="border: 1px solid black;">
|
||||
|
||||
</div>
|
||||
<h2>Help me to complete this example page on <a href="http://bazaar.launchpad.net/~openerp/openerp-web/trunk/view/head:/addons/web_rpc/static/src/example.html">launchpad</a></h2>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
[extractors]
|
||||
qweb = npybabel:extract_qweb
|
||||
xmljs = npybabel:extract_xmljs
|
||||
[javascript: static/src/js/**.js]
|
||||
[qweb: static/src/xml/**.xml]
|
||||
[xmljs: static/src/xml/**.xml]
|
||||
|
||||
|
||||
@@ -195,6 +195,13 @@ The new class can then be used in the following manner:
|
||||
After these two lines have executed (and any promise returned by ``appendTo``
|
||||
has been resolved if needed), the widget is ready to be used.
|
||||
|
||||
.. note:: the insertion methods will start the widget themselves, and will
|
||||
return the result of :js:func:`~openerp.base.Widget.start()`.
|
||||
|
||||
If for some reason you do not want to call these methods, you will
|
||||
have to first call :js:func:`~openerp.base.Widget.render()` on the
|
||||
widget, then insert it into your DOM and start it.
|
||||
|
||||
If the widget is not needed anymore (because it's transient), simply terminate
|
||||
it:
|
||||
|
||||
|
||||
+36
-17
@@ -5,15 +5,30 @@ import sys
|
||||
from pkg_resources import load_entry_point
|
||||
import re
|
||||
import json
|
||||
import xml.etree.ElementTree as elt
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(
|
||||
load_entry_point('Babel==0.9.6', 'console_scripts', 'pybabel')()
|
||||
)
|
||||
|
||||
QWEB_EXPR = re.compile(r"""(?:\< *t\-tr *\>(.*?)\< *\/t\-tr *\>)|(?:\_t *\( *((?:"(?:[^"\\]|\\.)*")|(?:'(?:[^'\\]|\\.)*')) *\))""")
|
||||
XML_GROUP = 1
|
||||
JS_GROUP = 2
|
||||
XMLJS_EXPR = re.compile(r"""(?:\_t *\( *((?:"(?:[^"\\]|\\.)*")|(?:'(?:[^'\\]|\\.)*')) *\))""")
|
||||
|
||||
def extract_xmljs(fileobj, keywords, comment_tags, options):
|
||||
content = fileobj.read()
|
||||
found = XMLJS_EXPR.finditer(content)
|
||||
result = []
|
||||
index = 0
|
||||
line_nbr = 0
|
||||
for f in found:
|
||||
mes = f.group(1)
|
||||
mes = json.loads(mes)
|
||||
while index < f.start():
|
||||
if content[index] == "\n":
|
||||
line_nbr += 1
|
||||
index += 1
|
||||
result.append((line_nbr, None, mes, ""))
|
||||
return result
|
||||
|
||||
def extract_qweb(fileobj, keywords, comment_tags, options):
|
||||
"""Extract messages from XXX files.
|
||||
@@ -28,19 +43,23 @@ def extract_qweb(fileobj, keywords, comment_tags, options):
|
||||
tuples
|
||||
:rtype: ``iterator``
|
||||
"""
|
||||
content = fileobj.read()
|
||||
found = QWEB_EXPR.finditer(content)
|
||||
result = []
|
||||
index = 0
|
||||
line_nbr = 0
|
||||
for f in found:
|
||||
group = XML_GROUP if f.group(XML_GROUP) else JS_GROUP
|
||||
mes = f.group(group)
|
||||
if group == JS_GROUP:
|
||||
mes = json.loads(mes)
|
||||
while index < f.start():
|
||||
if content[index] == "\n":
|
||||
line_nbr += 1
|
||||
index += 1
|
||||
result.append((line_nbr, None, mes, ""))
|
||||
def handle_text(str):
|
||||
str = (str or "").strip()
|
||||
if not str:
|
||||
return
|
||||
result.append((0, None, str, ""))
|
||||
|
||||
def iter_elements(current_element):
|
||||
for el in current_element:
|
||||
if "t-js" not in el.attrib and \
|
||||
not ("t-jquery" in el.attrib and "t-operation" not in el.attrib) and \
|
||||
not ("t-trad" in el.attrib and el.attrib["t-trad"].strip() == "off"):
|
||||
handle_text(el.text)
|
||||
iter_elements(el)
|
||||
handle_text(el.tail)
|
||||
|
||||
tree = elt.parse(fileobj)
|
||||
iter_elements(tree.getroot())
|
||||
|
||||
return result
|
||||
|
||||
+6
-6
@@ -28,7 +28,7 @@ DEFAULT_SERVER_DATETIME_FORMAT = "%s %s" % (
|
||||
DEFAULT_SERVER_DATE_FORMAT,
|
||||
DEFAULT_SERVER_TIME_FORMAT)
|
||||
|
||||
def parse_datetime(str):
|
||||
def str_to_datetime(str):
|
||||
"""
|
||||
Converts a string to a datetime object using OpenERP's
|
||||
datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
@@ -40,7 +40,7 @@ def parse_datetime(str):
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
def parse_date(str):
|
||||
def str_to_date(str):
|
||||
"""
|
||||
Converts a string to a date object using OpenERP's
|
||||
date string format (exemple: '2011-12-01').
|
||||
@@ -49,7 +49,7 @@ def parse_date(str):
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_DATE_FORMAT).date()
|
||||
|
||||
def parse_time(str):
|
||||
def str_to_time(str):
|
||||
"""
|
||||
Converts a string to a time object using OpenERP's
|
||||
time string format (exemple: '15:12:35').
|
||||
@@ -58,7 +58,7 @@ def parse_time(str):
|
||||
return str
|
||||
return datetime.datetime.strptime(str, DEFAULT_SERVER_TIME_FORMAT).time()
|
||||
|
||||
def format_datetime(obj):
|
||||
def datetime_to_str(obj):
|
||||
"""
|
||||
Converts a datetime object to a string using OpenERP's
|
||||
datetime string format (exemple: '2011-12-01 15:12:35').
|
||||
@@ -69,7 +69,7 @@ def format_datetime(obj):
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
def format_date(obj):
|
||||
def date_to_str(obj):
|
||||
"""
|
||||
Converts a date object to a string using OpenERP's
|
||||
date string format (exemple: '2011-12-01').
|
||||
@@ -78,7 +78,7 @@ def format_date(obj):
|
||||
return False
|
||||
return obj.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||
|
||||
def format_time(obj):
|
||||
def time_to_str(obj):
|
||||
"""
|
||||
Converts a time object to a string using OpenERP's
|
||||
time string format (exemple: '15:12:35').
|
||||
|
||||
+54
-61
@@ -233,7 +233,27 @@ class OpenERPSession(object):
|
||||
#----------------------------------------------------------
|
||||
# OpenERP Web RequestHandler
|
||||
#----------------------------------------------------------
|
||||
class JsonRequest(object):
|
||||
class CherryPyRequest(object):
|
||||
""" CherryPy request handling
|
||||
"""
|
||||
def init(self,params):
|
||||
self.params = params
|
||||
# Move cherrypy thread local objects to attributes
|
||||
self.applicationsession = applicationsession
|
||||
self.httprequest = cherrypy.request
|
||||
self.httpresponse = cherrypy.response
|
||||
self.httpsession = cherrypy.session
|
||||
self.httpsession_id = "cookieid"
|
||||
# OpenERP session setup
|
||||
self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex
|
||||
host = cherrypy.config['openerp.server.host']
|
||||
port = cherrypy.config['openerp.server.port']
|
||||
self.session = self.httpsession.setdefault(self.session_id, OpenERPSession(host, port))
|
||||
# Request attributes
|
||||
self.context = self.params.pop('context', None)
|
||||
self.debug = self.params.pop('debug',False) != False
|
||||
|
||||
class JsonRequest(CherryPyRequest):
|
||||
""" JSON-RPC2 over HTTP.
|
||||
|
||||
Sucessful request::
|
||||
@@ -267,48 +287,28 @@ class JsonRequest(object):
|
||||
|
||||
"""
|
||||
|
||||
def parse(self, request):
|
||||
self.request = request
|
||||
self.params = request.get("params", {})
|
||||
self.applicationsession = applicationsession
|
||||
self.httprequest = cherrypy.request
|
||||
self.httpresponse = cherrypy.response
|
||||
self.httpsession = cherrypy.session
|
||||
self.httpsession_id = "cookieid"
|
||||
self.httpsession = cherrypy.session
|
||||
self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex
|
||||
host = cherrypy.config['openerp.server.host']
|
||||
port = cherrypy.config['openerp.server.port']
|
||||
self.session = self.httpsession.setdefault(self.session_id, OpenERPSession(host, port))
|
||||
self.context = self.params.pop('context', None)
|
||||
return self.params
|
||||
|
||||
def dispatch(self, controller, method, requestf=None, request=None):
|
||||
""" Calls the method asked for by the JSON-RPC2 request
|
||||
|
||||
:param controller: the instance of the controller which received the request
|
||||
:type controller: type
|
||||
:param method: the method which received the request
|
||||
:type method: callable
|
||||
:param requestf: a file-like object containing an encoded JSON-RPC2 request
|
||||
:type requestf: <read() -> bytes>
|
||||
:param request: an encoded JSON-RPC2 request
|
||||
:type request: bytes
|
||||
:param request: a JSON-RPC2 request
|
||||
|
||||
:returns: a string-encoded JSON-RPC2 reply
|
||||
:rtype: bytes
|
||||
:returns: an utf8 encoded JSON-RPC2 reply
|
||||
"""
|
||||
# Read POST content or POST Form Data named "request"
|
||||
if requestf:
|
||||
request = simplejson.load(requestf, object_hook=nonliterals.non_literal_decoder)
|
||||
else:
|
||||
request = simplejson.loads(request, object_hook=nonliterals.non_literal_decoder)
|
||||
|
||||
response = {"jsonrpc": "2.0", "id": request.get('id')}
|
||||
response = {"jsonrpc": "2.0" }
|
||||
error = None
|
||||
try:
|
||||
print "--> %s.%s %s" % (controller.__class__.__name__, method.__name__, request)
|
||||
error = None
|
||||
self.parse(request)
|
||||
# Read POST content or POST Form Data named "request"
|
||||
if requestf:
|
||||
self.jsonrequest = simplejson.load(requestf, object_hook=nonliterals.non_literal_decoder)
|
||||
else:
|
||||
self.jsonrequest = simplejson.loads(request, object_hook=nonliterals.non_literal_decoder)
|
||||
self.init(self.jsonrequest.get("params", {}))
|
||||
if self.debug or 1:
|
||||
print "--> %s.%s %s" % (controller.__class__.__name__, method.__name__, self.jsonrequest)
|
||||
response['id'] = self.jsonrequest.get('id')
|
||||
response["result"] = method(controller, self, **self.params)
|
||||
except OpenERPUnboundException:
|
||||
error = {
|
||||
@@ -344,8 +344,9 @@ class JsonRequest(object):
|
||||
if error:
|
||||
response["error"] = error
|
||||
|
||||
print "<--", response
|
||||
print
|
||||
if self.debug or 1:
|
||||
print "<--", response
|
||||
print
|
||||
|
||||
content = simplejson.dumps(response, cls=nonliterals.NonLiteralEncoder)
|
||||
cherrypy.response.headers['Content-Type'] = 'application/json'
|
||||
@@ -357,40 +358,32 @@ def jsonrequest(f):
|
||||
@functools.wraps(f)
|
||||
def json_handler(controller):
|
||||
return JsonRequest().dispatch(controller, f, requestf=cherrypy.request.body)
|
||||
|
||||
return json_handler
|
||||
|
||||
class HttpRequest(object):
|
||||
class HttpRequest(CherryPyRequest):
|
||||
""" Regular GET/POST request
|
||||
"""
|
||||
def dispatch(self, controller, f, request, **kw):
|
||||
self.request = request
|
||||
self.applicationsession = applicationsession
|
||||
self.httpsession_id = "cookieid"
|
||||
self.httpsession = cherrypy.session
|
||||
self.context = kw.get('context', {})
|
||||
host = cherrypy.config['openerp.server.host']
|
||||
port = cherrypy.config['openerp.server.port']
|
||||
self.session = self.httpsession.setdefault(kw.pop('session_id', None), OpenERPSession(host, port))
|
||||
self.result = ""
|
||||
if request.method == 'GET':
|
||||
print "GET --> %s.%s %s %r" % (controller.__class__.__name__, f.__name__, request, kw)
|
||||
else:
|
||||
akw = dict([(key, kw[key] if isinstance(kw[key], basestring) else type(kw[key])) for key in kw.keys()])
|
||||
print "POST --> %s.%s %s %r" % (controller.__class__.__name__, f.__name__, request, akw)
|
||||
r = f(controller, self, **kw)
|
||||
if isinstance(r, str):
|
||||
print "<--", len(r), 'bytes'
|
||||
else:
|
||||
print "<--", len(r), 'characters'
|
||||
print
|
||||
def dispatch(self, controller, method, **kw):
|
||||
self.init(kw)
|
||||
akw = {}
|
||||
for key in kw.keys():
|
||||
if isinstance(kw[key], basestring) and len(kw[key]) < 1024:
|
||||
akw[key] = kw[key]
|
||||
else:
|
||||
akw[key] = type(kw[key])
|
||||
if self.debug or 1:
|
||||
print "%s --> %s.%s %r" % (self.httprequest.method, controller.__class__.__name__, method.__name__, akw)
|
||||
r = method(controller, self, **kw)
|
||||
if self.debug or 1:
|
||||
print "<--", 'size:', len(r)
|
||||
print
|
||||
return r
|
||||
|
||||
def httprequest(f):
|
||||
# check cleaner wrapping:
|
||||
# functools.wraps(f)(lambda x: JsonRequest().dispatch(x, f))
|
||||
def http_handler(self,*l, **kw):
|
||||
return HttpRequest().dispatch(self, f, cherrypy.request, **kw)
|
||||
def http_handler(controller,*l, **kw):
|
||||
return HttpRequest().dispatch(controller, f, **kw)
|
||||
http_handler.exposed = 1
|
||||
return http_handler
|
||||
|
||||
|
||||
Reference in New Issue
Block a user