[MERGE] merge from trunk
bzr revid: ged@openerp.com-20140502123355-9dqpwq1g9rrpisxj
This commit is contained in:
commit
132ccb7180
|
@ -14,83 +14,7 @@ This module provides the core of the OpenERP Web Client.
|
||||||
'data': [
|
'data': [
|
||||||
'views/webclient_templates.xml',
|
'views/webclient_templates.xml',
|
||||||
],
|
],
|
||||||
'js': [
|
|
||||||
"static/lib/es5-shim/es5-shim.min.js",
|
|
||||||
"static/lib/datejs/globalization/en-US.js",
|
|
||||||
"static/lib/datejs/core.js",
|
|
||||||
"static/lib/datejs/parser.js",
|
|
||||||
"static/lib/datejs/sugarpak.js",
|
|
||||||
"static/lib/datejs/extras.js",
|
|
||||||
"static/lib/jquery/jquery.js",
|
|
||||||
"static/lib/jquery.form/jquery.form.js",
|
|
||||||
"static/lib/jquery.validate/jquery.validate.js",
|
|
||||||
"static/lib/jquery.ba-bbq/jquery.ba-bbq.js",
|
|
||||||
"static/lib/spinjs/spin.js",
|
|
||||||
"static/lib/jquery.autosize/jquery.autosize.js",
|
|
||||||
"static/lib/jquery.blockUI/jquery.blockUI.js",
|
|
||||||
"static/lib/jquery.hotkeys/jquery.hotkeys.js",
|
|
||||||
"static/lib/jquery.placeholder/jquery.placeholder.js",
|
|
||||||
"static/lib/jquery.ui/js/jquery-ui-1.9.1.custom.js",
|
|
||||||
"static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js",
|
|
||||||
"static/lib/jquery.ui.notify/js/jquery.notify.js",
|
|
||||||
"static/lib/jquery.deferred-queue/jquery.deferred-queue.js",
|
|
||||||
"static/lib/jquery.scrollTo/jquery.scrollTo-min.js",
|
|
||||||
"static/lib/jquery.tipsy/jquery.tipsy.js",
|
|
||||||
"static/lib/jquery.textext/jquery.textext.js",
|
|
||||||
"static/lib/jquery.timeago/jquery.timeago.js",
|
|
||||||
"static/lib/bootstrap/js/bootstrap.js",
|
|
||||||
"static/lib/qweb/qweb2.js",
|
|
||||||
"static/lib/underscore/underscore.js",
|
|
||||||
"static/lib/underscore.string/lib/underscore.string.js",
|
|
||||||
"static/lib/backbone/backbone.js",
|
|
||||||
"static/lib/cleditor/jquery.cleditor.js",
|
|
||||||
"static/lib/py.js/lib/py.js",
|
|
||||||
"static/lib/select2/select2.js",
|
|
||||||
"static/src/js/openerpframework.js",
|
|
||||||
"static/src/js/boot.js",
|
|
||||||
"static/src/js/testing.js",
|
|
||||||
"static/src/js/pyeval.js",
|
|
||||||
"static/src/js/core.js",
|
|
||||||
"static/src/js/formats.js",
|
|
||||||
"static/src/js/chrome.js",
|
|
||||||
"static/src/js/views.js",
|
|
||||||
"static/src/js/data.js",
|
|
||||||
"static/src/js/data_export.js",
|
|
||||||
"static/src/js/search.js",
|
|
||||||
"static/src/js/view_list.js",
|
|
||||||
"static/src/js/view_form.js",
|
|
||||||
"static/src/js/view_list_editable.js",
|
|
||||||
"static/src/js/view_tree.js",
|
|
||||||
],
|
|
||||||
'css' : [
|
|
||||||
"static/lib/jquery.ui.bootstrap/css/custom-theme/jquery-ui-1.9.0.custom.css",
|
|
||||||
"static/lib/jquery.ui.timepicker/css/jquery-ui-timepicker-addon.css",
|
|
||||||
"static/lib/jquery.ui.notify/css/ui.notify.css",
|
|
||||||
"static/lib/jquery.tipsy/tipsy.css",
|
|
||||||
"static/lib/jquery.textext/jquery.textext.css",
|
|
||||||
"static/lib/fontawesome/css/font-awesome.css",
|
|
||||||
"static/lib/bootstrap/css/bootstrap.css",
|
|
||||||
"static/lib/select2/select2.css",
|
|
||||||
"static/src/css/base.css",
|
|
||||||
"static/src/css/data_export.css",
|
|
||||||
"static/lib/cleditor/jquery.cleditor.css",
|
|
||||||
],
|
|
||||||
'qweb' : [
|
'qweb' : [
|
||||||
"static/src/xml/*.xml",
|
"static/src/xml/*.xml",
|
||||||
],
|
],
|
||||||
'test': [
|
|
||||||
"static/test/testing.js",
|
|
||||||
"static/test/framework.js",
|
|
||||||
"static/test/registry.js",
|
|
||||||
"static/test/form.js",
|
|
||||||
"static/test/data.js",
|
|
||||||
"static/test/list-utils.js",
|
|
||||||
"static/test/formats.js",
|
|
||||||
"static/test/rpc-misordered.js",
|
|
||||||
"static/test/evals.js",
|
|
||||||
"static/test/search.js",
|
|
||||||
"static/test/list.js",
|
|
||||||
"static/test/list-editable.js",
|
|
||||||
"static/test/mutex.js"
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
from . import main
|
from . import main
|
||||||
from . import testing
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ except ImportError:
|
||||||
|
|
||||||
import openerp
|
import openerp
|
||||||
import openerp.modules.registry
|
import openerp.modules.registry
|
||||||
|
from openerp.addons.base.ir.ir_qweb import AssetsBundle, QWebTemplateNotFound
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
from openerp import http
|
from openerp import http
|
||||||
|
|
||||||
|
@ -52,50 +53,6 @@ env.filters["json"] = simplejson.dumps
|
||||||
# OpenERP Web helpers
|
# OpenERP Web helpers
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
|
|
||||||
def rjsmin(script):
|
|
||||||
""" Minify js with a clever regex.
|
|
||||||
Taken from http://opensource.perlig.de/rjsmin
|
|
||||||
Apache License, Version 2.0 """
|
|
||||||
def subber(match):
|
|
||||||
""" Substitution callback """
|
|
||||||
groups = match.groups()
|
|
||||||
return (
|
|
||||||
groups[0] or
|
|
||||||
groups[1] or
|
|
||||||
groups[2] or
|
|
||||||
groups[3] or
|
|
||||||
(groups[4] and '\n') or
|
|
||||||
(groups[5] and ' ') or
|
|
||||||
(groups[6] and ' ') or
|
|
||||||
(groups[7] and ' ') or
|
|
||||||
''
|
|
||||||
)
|
|
||||||
|
|
||||||
result = re.sub(
|
|
||||||
r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?'
|
|
||||||
r'\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|'
|
|
||||||
r'\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?:(?<=[(,=:\[!&|?{};\r\n]'
|
|
||||||
r')(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/'
|
|
||||||
r'))*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*'
|
|
||||||
r'(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/)[^\047"/\000-\040]*'
|
|
||||||
r'))|(?:(?<=[\000-#%-,./:-@\[-^`{-~-]return)(?:[\000-\011\013\014\01'
|
|
||||||
r'6-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*((?:/(?![\r\n/*])[^/'
|
|
||||||
r'\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]'
|
|
||||||
r'*)*\]))[^/\\\[\r\n]*)*/)[^\047"/\000-\040]*))|(?<=[^\000-!#%&(*,./'
|
|
||||||
r':-@\[\\^`{|~])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/'
|
|
||||||
r'*][^*]*\*+)*/))*(?:((?:(?://[^\r\n]*)?[\r\n]))(?:[\000-\011\013\01'
|
|
||||||
r'4\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040"#'
|
|
||||||
r'%-\047)*,./:-@\\-^`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-'
|
|
||||||
r'\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=[^'
|
|
||||||
r'\000-#%-,./:-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|'
|
|
||||||
r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=\+)|(?<=-)((?:[\000-\011\0'
|
|
||||||
r'13\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=-)|(?:[\0'
|
|
||||||
r'00-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+|(?:'
|
|
||||||
r'(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*'
|
|
||||||
r']*\*+(?:[^/*][^*]*\*+)*/))*)+', subber, '\n%s\n' % script
|
|
||||||
).strip()
|
|
||||||
return result
|
|
||||||
|
|
||||||
db_list = http.db_list
|
db_list = http.db_list
|
||||||
|
|
||||||
db_monodb = http.db_monodb
|
db_monodb = http.db_monodb
|
||||||
|
@ -309,45 +266,6 @@ def concat_xml(file_list):
|
||||||
root.append(child)
|
root.append(child)
|
||||||
return ElementTree.tostring(root, 'utf-8'), checksum.hexdigest()
|
return ElementTree.tostring(root, 'utf-8'), checksum.hexdigest()
|
||||||
|
|
||||||
def concat_files(file_list, reader=None, intersperse=""):
|
|
||||||
""" Concatenates contents of all provided files
|
|
||||||
|
|
||||||
:param list(str) file_list: list of files to check
|
|
||||||
:param function reader: reading procedure for each file
|
|
||||||
:param str intersperse: string to intersperse between file contents
|
|
||||||
:returns: (concatenation_result, checksum)
|
|
||||||
:rtype: (str, str)
|
|
||||||
"""
|
|
||||||
checksum = hashlib.new('sha1')
|
|
||||||
if not file_list:
|
|
||||||
return '', checksum.hexdigest()
|
|
||||||
|
|
||||||
if reader is None:
|
|
||||||
def reader(f):
|
|
||||||
import codecs
|
|
||||||
with codecs.open(f, 'rb', "utf-8-sig") as fp:
|
|
||||||
return fp.read().encode("utf-8")
|
|
||||||
|
|
||||||
files_content = []
|
|
||||||
for fname in file_list:
|
|
||||||
contents = reader(fname)
|
|
||||||
checksum.update(contents)
|
|
||||||
files_content.append(contents)
|
|
||||||
|
|
||||||
files_concat = intersperse.join(files_content)
|
|
||||||
return files_concat, checksum.hexdigest()
|
|
||||||
|
|
||||||
concat_js_cache = {}
|
|
||||||
|
|
||||||
def concat_js(file_list):
|
|
||||||
content, checksum = concat_files(file_list, intersperse=';')
|
|
||||||
if checksum in concat_js_cache:
|
|
||||||
content = concat_js_cache[checksum]
|
|
||||||
else:
|
|
||||||
content = rjsmin(content)
|
|
||||||
concat_js_cache[checksum] = content
|
|
||||||
return content, checksum
|
|
||||||
|
|
||||||
def fs2web(path):
|
def fs2web(path):
|
||||||
"""convert FS path into web path"""
|
"""convert FS path into web path"""
|
||||||
return '/'.join(path.split(os.path.sep))
|
return '/'.join(path.split(os.path.sep))
|
||||||
|
@ -371,30 +289,17 @@ def manifest_glob(extension, addons=None, db=None, include_remotes=False):
|
||||||
r.append((None, pattern))
|
r.append((None, pattern))
|
||||||
else:
|
else:
|
||||||
for path in glob.glob(os.path.normpath(os.path.join(addons_path, addon, pattern))):
|
for path in glob.glob(os.path.normpath(os.path.join(addons_path, addon, pattern))):
|
||||||
# Hack for IE, who limit 288Ko, 4095 rules, 31 sheets
|
r.append((path, fs2web(path[len(addons_path):])))
|
||||||
# http://support.microsoft.com/kb/262161/en
|
|
||||||
if pattern == "static/lib/bootstrap/css/bootstrap.css":
|
|
||||||
if include_remotes:
|
|
||||||
r.insert(0, (None, fs2web(path[len(addons_path):])))
|
|
||||||
else:
|
|
||||||
r.append((path, fs2web(path[len(addons_path):])))
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def manifest_list(extension, mods=None, db=None, debug=False):
|
def manifest_list(extension, mods=None, db=None, debug=None):
|
||||||
""" list ressources to load specifying either:
|
""" list ressources to load specifying either:
|
||||||
mods: a comma separated string listing modules
|
mods: a comma separated string listing modules
|
||||||
db: a database name (return all installed modules in that database)
|
db: a database name (return all installed modules in that database)
|
||||||
"""
|
"""
|
||||||
|
if debug is not None:
|
||||||
|
_logger.warning("openerp.addons.web.main.manifest_list(): debug parameter is deprecated")
|
||||||
files = manifest_glob(extension, addons=mods, db=db, include_remotes=True)
|
files = manifest_glob(extension, addons=mods, db=db, include_remotes=True)
|
||||||
if not debug:
|
|
||||||
path = '/web/webclient/' + extension
|
|
||||||
if mods is not None:
|
|
||||||
path += '?' + werkzeug.url_encode({'mods': mods})
|
|
||||||
elif db:
|
|
||||||
path += '?' + werkzeug.url_encode({'db': db})
|
|
||||||
|
|
||||||
remotes = [wp for fp, wp in files if fp is None]
|
|
||||||
return [path] + remotes
|
|
||||||
return [wp for _fp, wp in files]
|
return [wp for _fp, wp in files]
|
||||||
|
|
||||||
def get_last_modified(files):
|
def get_last_modified(files):
|
||||||
|
@ -411,7 +316,7 @@ def get_last_modified(files):
|
||||||
for f in files)
|
for f in files)
|
||||||
return datetime.datetime(1970, 1, 1)
|
return datetime.datetime(1970, 1, 1)
|
||||||
|
|
||||||
def make_conditional(response, last_modified=None, etag=None):
|
def make_conditional(response, last_modified=None, etag=None, max_age=0):
|
||||||
""" Makes the provided response conditional based upon the request,
|
""" Makes the provided response conditional based upon the request,
|
||||||
and mandates revalidation from clients
|
and mandates revalidation from clients
|
||||||
|
|
||||||
|
@ -426,7 +331,7 @@ def make_conditional(response, last_modified=None, etag=None):
|
||||||
:rtype: werkzeug.wrappers.Response
|
:rtype: werkzeug.wrappers.Response
|
||||||
"""
|
"""
|
||||||
response.cache_control.must_revalidate = True
|
response.cache_control.must_revalidate = True
|
||||||
response.cache_control.max_age = 0
|
response.cache_control.max_age = max_age
|
||||||
if last_modified:
|
if last_modified:
|
||||||
response.last_modified = last_modified
|
response.last_modified = last_modified
|
||||||
if etag:
|
if etag:
|
||||||
|
@ -603,6 +508,7 @@ html_template = """<!DOCTYPE html>
|
||||||
<title>OpenERP</title>
|
<title>OpenERP</title>
|
||||||
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
|
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
|
||||||
<link rel="stylesheet" href="/web/static/src/css/full.css" />
|
<link rel="stylesheet" href="/web/static/src/css/full.css" />
|
||||||
|
|
||||||
%(css)s
|
%(css)s
|
||||||
%(js)s
|
%(js)s
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -621,26 +527,16 @@ html_template = """<!DOCTYPE html>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def render_bootstrap_template(template, values=None, debug=False, db=None, **kw):
|
def render_bootstrap_template(template, values=None, **kw):
|
||||||
if not db:
|
|
||||||
db = request.db
|
|
||||||
if request.debug:
|
|
||||||
debug = True
|
|
||||||
if values is None:
|
if values is None:
|
||||||
values = {}
|
values = dict()
|
||||||
values['debug'] = debug
|
|
||||||
values['current_db'] = db
|
|
||||||
try:
|
try:
|
||||||
values['databases'] = http.db_list()
|
values['databases'] = http.db_list()
|
||||||
except openerp.exceptions.AccessDenied:
|
except openerp.exceptions.AccessDenied:
|
||||||
values['databases'] = None
|
values['databases'] = None
|
||||||
|
|
||||||
for res in ['js', 'css']:
|
|
||||||
if res not in values:
|
|
||||||
values[res] = manifest_list(res, db=db, debug=debug)
|
|
||||||
|
|
||||||
if 'modules' not in values:
|
if 'modules' not in values:
|
||||||
values['modules'] = module_boot(db=db)
|
values['modules'] = module_boot()
|
||||||
values['modules'] = simplejson.dumps(values['modules'])
|
values['modules'] = simplejson.dumps(values['modules'])
|
||||||
|
|
||||||
return request.render(template, values, **kw)
|
return request.render(template, values, **kw)
|
||||||
|
@ -682,9 +578,11 @@ class Home(http.Controller):
|
||||||
redirect = '/web?' + request.httprequest.query_string
|
redirect = '/web?' + request.httprequest.query_string
|
||||||
values['redirect'] = redirect
|
values['redirect'] = redirect
|
||||||
if request.httprequest.method == 'POST':
|
if request.httprequest.method == 'POST':
|
||||||
|
old_uid = request.uid
|
||||||
uid = request.session.authenticate(request.session.db, request.params['login'], request.params['password'])
|
uid = request.session.authenticate(request.session.db, request.params['login'], request.params['password'])
|
||||||
if uid is not False:
|
if uid is not False:
|
||||||
return http.redirect_with_hash(redirect)
|
return http.redirect_with_hash(redirect)
|
||||||
|
request.uid = old_uid
|
||||||
values['error'] = "Wrong login/password"
|
values['error'] = "Wrong login/password"
|
||||||
return render_bootstrap_template('web.login', values)
|
return render_bootstrap_template('web.login', values)
|
||||||
|
|
||||||
|
@ -692,6 +590,38 @@ class Home(http.Controller):
|
||||||
def login(self, db, login, key, redirect="/web", **kw):
|
def login(self, db, login, key, redirect="/web", **kw):
|
||||||
return login_and_redirect(db, login, key, redirect_url=redirect)
|
return login_and_redirect(db, login, key, redirect_url=redirect)
|
||||||
|
|
||||||
|
@http.route('/web/js/<xmlid>', type='http', auth="public")
|
||||||
|
def js_bundle(self, xmlid, **kw):
|
||||||
|
# manifest backward compatible mode, to be removed
|
||||||
|
values = {'manifest_list': manifest_list}
|
||||||
|
try:
|
||||||
|
assets_html = request.render(xmlid, lazy=False, qcontext=values)
|
||||||
|
except QWebTemplateNotFound:
|
||||||
|
return request.not_found()
|
||||||
|
bundle = AssetsBundle(xmlid, assets_html, debug=request.debug)
|
||||||
|
|
||||||
|
response = request.make_response(
|
||||||
|
bundle.js(), [('Content-Type', 'application/javascript')])
|
||||||
|
|
||||||
|
# TODO: check that we don't do weird lazy overriding of __call__ which break body-removal
|
||||||
|
return make_conditional(
|
||||||
|
response, bundle.last_modified, bundle.checksum, max_age=60*60*24)
|
||||||
|
|
||||||
|
@http.route('/web/css/<xmlid>', type='http', auth='public')
|
||||||
|
def css_bundle(self, xmlid, **kw):
|
||||||
|
values = {'manifest_list': manifest_list} # manifest backward compatible mode, to be removed
|
||||||
|
try:
|
||||||
|
assets_html = request.render(xmlid, lazy=False, qcontext=values)
|
||||||
|
except QWebTemplateNotFound:
|
||||||
|
return request.not_found()
|
||||||
|
bundle = AssetsBundle(xmlid, assets_html, debug=request.debug)
|
||||||
|
|
||||||
|
response = request.make_response(
|
||||||
|
bundle.css(), [('Content-Type', 'text/css')])
|
||||||
|
|
||||||
|
return make_conditional(
|
||||||
|
response, bundle.last_modified, bundle.checksum, max_age=60*60*24)
|
||||||
|
|
||||||
class WebClient(http.Controller):
|
class WebClient(http.Controller):
|
||||||
|
|
||||||
@http.route('/web/webclient/csslist', type='json', auth="none")
|
@http.route('/web/webclient/csslist', type='json', auth="none")
|
||||||
|
@ -702,74 +632,6 @@ class WebClient(http.Controller):
|
||||||
def jslist(self, mods=None):
|
def jslist(self, mods=None):
|
||||||
return manifest_list('js', mods=mods)
|
return manifest_list('js', mods=mods)
|
||||||
|
|
||||||
@http.route('/web/webclient/qweblist', type='json', auth="none")
|
|
||||||
def qweblist(self, mods=None):
|
|
||||||
return manifest_list('qweb', mods=mods)
|
|
||||||
|
|
||||||
@http.route('/web/webclient/css', type='http', auth="none")
|
|
||||||
def css(self, mods=None, db=None):
|
|
||||||
files = list(manifest_glob('css', addons=mods, db=db))
|
|
||||||
last_modified = get_last_modified(f[0] for f in files)
|
|
||||||
if request.httprequest.if_modified_since and request.httprequest.if_modified_since >= last_modified:
|
|
||||||
return werkzeug.wrappers.Response(status=304)
|
|
||||||
|
|
||||||
file_map = dict(files)
|
|
||||||
|
|
||||||
rx_import = re.compile(r"""@import\s+('|")(?!'|"|/|https?://)""", re.U)
|
|
||||||
rx_url = re.compile(r"""url\s*\(\s*('|"|)(?!'|"|/|https?://|data:)""", re.U)
|
|
||||||
|
|
||||||
def reader(f):
|
|
||||||
"""read the a css file and absolutify all relative uris"""
|
|
||||||
with open(f, 'rb') as fp:
|
|
||||||
data = fp.read().decode('utf-8')
|
|
||||||
|
|
||||||
path = file_map[f]
|
|
||||||
web_dir = os.path.dirname(path)
|
|
||||||
|
|
||||||
data = re.sub(
|
|
||||||
rx_import,
|
|
||||||
r"""@import \1%s/""" % (web_dir,),
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
|
|
||||||
data = re.sub(
|
|
||||||
rx_url,
|
|
||||||
r"url(\1%s/" % (web_dir,),
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
return data.encode('utf-8')
|
|
||||||
|
|
||||||
content, checksum = concat_files((f[0] for f in files), reader)
|
|
||||||
|
|
||||||
# move up all @import and @charset rules to the top
|
|
||||||
matches = []
|
|
||||||
def push(matchobj):
|
|
||||||
matches.append(matchobj.group(0))
|
|
||||||
return ''
|
|
||||||
|
|
||||||
content = re.sub(re.compile("(@charset.+;$)", re.M), push, content)
|
|
||||||
content = re.sub(re.compile("(@import.+;$)", re.M), push, content)
|
|
||||||
|
|
||||||
matches.append(content)
|
|
||||||
content = '\n'.join(matches)
|
|
||||||
|
|
||||||
return make_conditional(
|
|
||||||
request.make_response(content, [('Content-Type', 'text/css')]),
|
|
||||||
last_modified, checksum)
|
|
||||||
|
|
||||||
@http.route('/web/webclient/js', type='http', auth="none")
|
|
||||||
def js(self, mods=None, db=None):
|
|
||||||
files = [f[0] for f in manifest_glob('js', addons=mods, db=db)]
|
|
||||||
last_modified = get_last_modified(files)
|
|
||||||
if request.httprequest.if_modified_since and request.httprequest.if_modified_since >= last_modified:
|
|
||||||
return werkzeug.wrappers.Response(status=304)
|
|
||||||
|
|
||||||
content, checksum = concat_js(files)
|
|
||||||
|
|
||||||
return make_conditional(
|
|
||||||
request.make_response(content, [('Content-Type', 'application/javascript')]),
|
|
||||||
last_modified, checksum)
|
|
||||||
|
|
||||||
@http.route('/web/webclient/qweb', type='http', auth="none")
|
@http.route('/web/webclient/qweb', type='http', auth="none")
|
||||||
def qweb(self, mods=None, db=None):
|
def qweb(self, mods=None, db=None):
|
||||||
files = [f[0] for f in manifest_glob('qweb', addons=mods, db=db)]
|
files = [f[0] for f in manifest_glob('qweb', addons=mods, db=db)]
|
||||||
|
@ -843,6 +705,10 @@ class WebClient(http.Controller):
|
||||||
def version_info(self):
|
def version_info(self):
|
||||||
return openerp.service.common.exp_version()
|
return openerp.service.common.exp_version()
|
||||||
|
|
||||||
|
@http.route('/web/tests', type='http', auth="none")
|
||||||
|
def index(self, mod=None, **kwargs):
|
||||||
|
return request.render('web.qunit_suite')
|
||||||
|
|
||||||
class Proxy(http.Controller):
|
class Proxy(http.Controller):
|
||||||
|
|
||||||
@http.route('/web/proxy/load', type='json', auth="none")
|
@http.route('/web/proxy/load', type='json', auth="none")
|
||||||
|
@ -879,8 +745,64 @@ class Database(http.Controller):
|
||||||
def manager(self, **kw):
|
def manager(self, **kw):
|
||||||
# TODO: migrate the webclient's database manager to server side views
|
# TODO: migrate the webclient's database manager to server side views
|
||||||
request.session.logout()
|
request.session.logout()
|
||||||
js = "\n ".join('<script type="text/javascript" src="%s"></script>' % i for i in manifest_list('js', debug=request.debug))
|
css = """
|
||||||
css = "\n ".join('<link rel="stylesheet" href="%s">' % i for i in manifest_list('css', debug=request.debug))
|
<link href="/web/static/lib/fontawesome/css/font-awesome.css" rel="stylesheet"/>
|
||||||
|
<link href="/web/static/lib/cleditor/jquery.cleditor.css" rel="stylesheet"/>
|
||||||
|
<link href="/web/static/lib/jquery.textext/jquery.textext.css" rel="stylesheet"/>
|
||||||
|
<link href="/web/static/lib/select2/select2.css" rel="stylesheet"/>
|
||||||
|
<link href="/web/static/lib/jquery.ui.bootstrap/css/custom-theme/jquery-ui-1.9.0.custom.css" rel="stylesheet"/>
|
||||||
|
<link href="/web/static/lib/jquery.ui.timepicker/css/jquery-ui-timepicker-addon.css" rel="stylesheet"/>
|
||||||
|
<link href="/web/static/lib/jquery.ui.notify/css/ui.notify.css" rel="stylesheet"/>
|
||||||
|
<link href="/web/static/lib/bootstrap/css/bootstrap.css" rel="stylesheet"/>
|
||||||
|
<link href="/web/static/src/css/base.css" rel="stylesheet"/>
|
||||||
|
<link href="/web/static/src/css/data_export.css" rel="stylesheet"/>
|
||||||
|
<link href="/base/static/src/css/modules.css" rel="stylesheet"/>"""
|
||||||
|
js = """
|
||||||
|
<script src="/web/static/lib/es5-shim/es5-shim.min.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/underscore/underscore.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/underscore.string/lib/underscore.string.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/datejs/globalization/en-US.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/spinjs/spin.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery/jquery.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.blockUI/jquery.blockUI.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.hotkeys/jquery.hotkeys.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.placeholder/jquery.placeholder.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.timeago/jquery.timeago.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.form/jquery.form.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/datejs/core.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/datejs/parser.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/datejs/sugarpak.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/datejs/extras.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.validate/jquery.validate.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.autosize/jquery.autosize.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.scrollTo/jquery.scrollTo-min.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/cleditor/jquery.cleditor.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.textext/jquery.textext.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/select2/select2.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.ui/js/jquery-ui-1.9.1.custom.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/jquery.ui.notify/js/jquery.notify.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/bootstrap/js/bootstrap.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/backbone/backbone.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/qweb/qweb2.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/openerpframework.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/lib/py.js/lib/py.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/boot.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/testing.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/pyeval.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/core.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/formats.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/chrome.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/views.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/data.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/data_export.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/search.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/view_list.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/view_form.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/view_list_editable.js" type="text/javascript"></script>
|
||||||
|
<script src="/web/static/src/js/view_tree.js" type="text/javascript"></script>
|
||||||
|
<script src="/base/static/src/js/apps.js" type="text/javascript"></script>"""
|
||||||
|
|
||||||
r = html_template % {
|
r = html_template % {
|
||||||
'js': js,
|
'js': js,
|
||||||
|
@ -1088,16 +1010,7 @@ class Menu(http.Controller):
|
||||||
"""
|
"""
|
||||||
s = request.session
|
s = request.session
|
||||||
Menus = s.model('ir.ui.menu')
|
Menus = s.model('ir.ui.menu')
|
||||||
# If a menu action is defined use its domain to get the root menu items
|
|
||||||
user_menu_id = s.model('res.users').read([s.uid], ['menu_id'],
|
|
||||||
request.context)[0]['menu_id']
|
|
||||||
|
|
||||||
menu_domain = [('parent_id', '=', False)]
|
menu_domain = [('parent_id', '=', False)]
|
||||||
if user_menu_id:
|
|
||||||
domain_string = s.model('ir.actions.act_window').read(
|
|
||||||
[user_menu_id[0]], ['domain'],request.context)[0]['domain']
|
|
||||||
if domain_string:
|
|
||||||
menu_domain = ast.literal_eval(domain_string)
|
|
||||||
|
|
||||||
return Menus.search(menu_domain, 0, False, False, request.context)
|
return Menus.search(menu_domain, 0, False, False, request.context)
|
||||||
|
|
||||||
|
@ -1225,7 +1138,7 @@ class DataSet(http.Controller):
|
||||||
records = getattr(request.session.model(model), method)(*args, **kwargs)
|
records = getattr(request.session.model(model), method)(*args, **kwargs)
|
||||||
for record in records:
|
for record in records:
|
||||||
record['display_name'] = \
|
record['display_name'] = \
|
||||||
names.get(record['id']) or "%s#%d" % (model, (record['id']))
|
names.get(record['id']) or "{0}#{1}".format(model, (record['id']))
|
||||||
return records
|
return records
|
||||||
|
|
||||||
if method.startswith('_'):
|
if method.startswith('_'):
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
# coding=utf-8
|
|
||||||
# -*- encoding: utf-8 -*-
|
|
||||||
|
|
||||||
import glob
|
|
||||||
import itertools
|
|
||||||
import json
|
|
||||||
import operator
|
|
||||||
import os
|
|
||||||
|
|
||||||
from mako.template import Template
|
|
||||||
from openerp.modules import module
|
|
||||||
from openerp import http
|
|
||||||
from openerp.http import request
|
|
||||||
|
|
||||||
from .main import module_topological_sort
|
|
||||||
|
|
||||||
NOMODULE_TEMPLATE = Template(u"""<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
|
||||||
<title>OpenERP Testing</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form action="/web/tests" method="GET">
|
|
||||||
<button name="mod" value="*">Run all tests</button>
|
|
||||||
<ul>
|
|
||||||
% for name, module in modules:
|
|
||||||
<li>${name} <button name="mod" value="${module}">
|
|
||||||
Run Tests</button></li>
|
|
||||||
% endfor
|
|
||||||
</ul>
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
""", default_filters=['h'])
|
|
||||||
NOTFOUND = Template(u"""
|
|
||||||
<p>Unable to find the module [${module}], please check that the module
|
|
||||||
name is correct and the module is on OpenERP's path.</p>
|
|
||||||
<a href="/web/tests"><< Back to tests</a>
|
|
||||||
""", default_filters=['h'])
|
|
||||||
TESTING = Template(u"""<!DOCTYPE html>
|
|
||||||
<html style="height: 100%">
|
|
||||||
<%def name="to_path(module, p)">/${module}/${p}</%def>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
|
||||||
<title>OpenERP Web Tests</title>
|
|
||||||
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="/web/static/lib/qunit/qunit.css">
|
|
||||||
<script src="/web/static/lib/qunit/qunit.js"></script>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
// List of modules, each module is preceded by its dependencies
|
|
||||||
var oe_all_dependencies = ${dependencies | n};
|
|
||||||
QUnit.config.testTimeout = 5 * 60 * 1000;
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body id="oe" class="openerp">
|
|
||||||
<div id="qunit"></div>
|
|
||||||
<div id="qunit-fixture"></div>
|
|
||||||
</body>
|
|
||||||
<!-- TODO xmo please use the regular template even for testing -->
|
|
||||||
% for module, jss, tests, templates in files:
|
|
||||||
% for js in jss:
|
|
||||||
% if not js.endswith('/apps.js'):
|
|
||||||
<script src="${to_path(module, js)}"></script>
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
% if tests or templates:
|
|
||||||
<script>
|
|
||||||
openerp.testing.current_module = "${module}";
|
|
||||||
% for template in templates:
|
|
||||||
openerp.testing.add_template("${to_path(module, template)}");
|
|
||||||
% endfor
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
% if tests:
|
|
||||||
% for test in tests:
|
|
||||||
<script type="text/javascript" src="${to_path(module, test)}"></script>
|
|
||||||
% endfor
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
</html>
|
|
||||||
""", default_filters=['h'])
|
|
||||||
|
|
||||||
class TestRunnerController(http.Controller):
|
|
||||||
|
|
||||||
@http.route('/web/tests', type='http', auth="none")
|
|
||||||
def index(self, mod=None, **kwargs):
|
|
||||||
ms = module.get_modules()
|
|
||||||
manifests = dict(
|
|
||||||
(name, desc)
|
|
||||||
for name, desc in zip(ms, map(self.load_manifest, ms))
|
|
||||||
if desc # remove not-actually-openerp-modules
|
|
||||||
)
|
|
||||||
|
|
||||||
if not mod:
|
|
||||||
return NOMODULE_TEMPLATE.render(modules=(
|
|
||||||
(manifest['name'], name)
|
|
||||||
for name, manifest in manifests.iteritems()
|
|
||||||
if any(testfile.endswith('.js')
|
|
||||||
for testfile in manifest['test'])
|
|
||||||
))
|
|
||||||
sorted_mods = module_topological_sort(dict(
|
|
||||||
(name, manifest.get('depends', []))
|
|
||||||
for name, manifest in manifests.iteritems()
|
|
||||||
))
|
|
||||||
# to_load and to_test should be zippable lists of the same length.
|
|
||||||
# A falsy value in to_test indicate nothing to test at that index (just
|
|
||||||
# load the corresponding part of to_load)
|
|
||||||
to_test = sorted_mods
|
|
||||||
if mod != '*':
|
|
||||||
if mod not in manifests:
|
|
||||||
return request.not_found(NOTFOUND.render(module=mod))
|
|
||||||
idx = sorted_mods.index(mod)
|
|
||||||
to_test = [None] * len(sorted_mods)
|
|
||||||
to_test[idx] = mod
|
|
||||||
|
|
||||||
tests_candicates = [
|
|
||||||
filter(lambda path: path.endswith('.js'),
|
|
||||||
manifests[mod]['test'] if mod else [])
|
|
||||||
for mod in to_test]
|
|
||||||
# remove trailing test-less modules
|
|
||||||
tests = reversed(list(
|
|
||||||
itertools.dropwhile(
|
|
||||||
operator.not_,
|
|
||||||
reversed(tests_candicates))))
|
|
||||||
|
|
||||||
files = [
|
|
||||||
(mod, manifests[mod]['js'], tests, manifests[mod]['qweb'])
|
|
||||||
for mod, tests in itertools.izip(sorted_mods, tests)
|
|
||||||
]
|
|
||||||
|
|
||||||
return TESTING.render(files=files, dependencies=json.dumps(
|
|
||||||
[name for name in sorted_mods
|
|
||||||
if module.get_module_resource(name, 'static')
|
|
||||||
if manifests[name]['js']]))
|
|
||||||
|
|
||||||
def load_manifest(self, name):
|
|
||||||
manifest = module.load_information_from_description_file(name)
|
|
||||||
if manifest:
|
|
||||||
path = module.get_module_path(name)
|
|
||||||
manifest['js'] = list(
|
|
||||||
self.expand_patterns(path, manifest.get('js', [])))
|
|
||||||
manifest['test'] = list(
|
|
||||||
self.expand_patterns(path, manifest.get('test', [])))
|
|
||||||
manifest['qweb'] = list(
|
|
||||||
self.expand_patterns(path, manifest.get('qweb', [])))
|
|
||||||
return manifest
|
|
||||||
|
|
||||||
def expand_patterns(self, root, patterns):
|
|
||||||
for pattern in patterns:
|
|
||||||
normalized_pattern = os.path.normpath(os.path.join(root, pattern))
|
|
||||||
for path in glob.glob(normalized_pattern):
|
|
||||||
# replace OS path separators (from join & normpath) by URI ones
|
|
||||||
yield path[len(root):].replace(os.path.sep, '/')
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
"X-Poedit-Language: Czech\n"
|
"X-Poedit-Language: Czech\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
"Language: es\n"
|
"Language: es\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-10 05:56+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -15,8 +15,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:38+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:52+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:39+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:53+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web
|
#. module: web
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -1,250 +0,0 @@
|
||||||
// tipsy, facebook style tooltips for jquery
|
|
||||||
// version 1.0.0a
|
|
||||||
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
|
|
||||||
// released under the MIT license
|
|
||||||
|
|
||||||
(function($) {
|
|
||||||
|
|
||||||
function maybeCall(thing, ctx) {
|
|
||||||
return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
|
|
||||||
};
|
|
||||||
|
|
||||||
function Tipsy(element, options) {
|
|
||||||
this.$element = $(element);
|
|
||||||
this.options = options;
|
|
||||||
this.enabled = true;
|
|
||||||
this.fixTitle();
|
|
||||||
};
|
|
||||||
|
|
||||||
Tipsy.prototype = {
|
|
||||||
show: function() {
|
|
||||||
$.fn.tipsy.clear();
|
|
||||||
if (!this.$element.parent().length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var title = this.getTitle();
|
|
||||||
if (title && this.enabled) {
|
|
||||||
var $tip = this.tip();
|
|
||||||
|
|
||||||
$tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
|
|
||||||
$tip[0].className = 'tipsy '; // reset classname in case of dynamic gravity
|
|
||||||
$tip.openerpClass('oe_tooltip');
|
|
||||||
$tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);
|
|
||||||
|
|
||||||
var pos = $.extend({}, this.$element.offset(), {
|
|
||||||
width: this.$element[0].offsetWidth,
|
|
||||||
height: this.$element[0].offsetHeight
|
|
||||||
});
|
|
||||||
|
|
||||||
var actualWidth = $tip[0].offsetWidth,
|
|
||||||
actualHeight = $tip[0].offsetHeight,
|
|
||||||
gravity = maybeCall(this.options.gravity, this.$element[0]);
|
|
||||||
|
|
||||||
var tp;
|
|
||||||
switch (gravity.charAt(0)) {
|
|
||||||
case 'n':
|
|
||||||
tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gravity.length == 2) {
|
|
||||||
if (gravity.charAt(1) == 'w') {
|
|
||||||
tp.left = pos.left + pos.width / 2 - 15;
|
|
||||||
} else {
|
|
||||||
tp.left = pos.left + pos.width / 2 - actualWidth + 15;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$tip.css(tp).addClass('tipsy-' + gravity);
|
|
||||||
$tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0);
|
|
||||||
if (this.options.className) {
|
|
||||||
$tip.addClass(maybeCall(this.options.className, this.$element[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.options.fade) {
|
|
||||||
$tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
|
|
||||||
} else {
|
|
||||||
$tip.css({visibility: 'visible', opacity: this.options.opacity});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
hide: function() {
|
|
||||||
if (this.options.fade) {
|
|
||||||
this.tip().stop().fadeOut(function() { $(this).remove(); });
|
|
||||||
} else {
|
|
||||||
this.tip().remove();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
fixTitle: function() {
|
|
||||||
var $e = this.$element;
|
|
||||||
if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
|
|
||||||
$e.attr('original-title', $e.attr('title') || '').removeAttr('title');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getTitle: function() {
|
|
||||||
var title, $e = this.$element, o = this.options;
|
|
||||||
this.fixTitle();
|
|
||||||
var title, o = this.options;
|
|
||||||
if (typeof o.title == 'string') {
|
|
||||||
title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
|
|
||||||
} else if (typeof o.title == 'function') {
|
|
||||||
title = o.title.call($e[0]);
|
|
||||||
}
|
|
||||||
title = ('' + title).replace(/(^\s*|\s*$)/, "");
|
|
||||||
return title || o.fallback;
|
|
||||||
},
|
|
||||||
|
|
||||||
tip: function() {
|
|
||||||
if (!this.$tip) {
|
|
||||||
this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
|
|
||||||
}
|
|
||||||
return this.$tip;
|
|
||||||
},
|
|
||||||
|
|
||||||
validate: function() {
|
|
||||||
if (!this.$element[0].parentNode) {
|
|
||||||
this.hide();
|
|
||||||
this.$element = null;
|
|
||||||
this.options = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
enable: function() { this.enabled = true; },
|
|
||||||
disable: function() { this.enabled = false; },
|
|
||||||
toggleEnabled: function() { this.enabled = !this.enabled; }
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.tipsy = function(options) {
|
|
||||||
|
|
||||||
if (options === true) {
|
|
||||||
return this.data('tipsy');
|
|
||||||
} else if (typeof options == 'string') {
|
|
||||||
var tipsy = this.data('tipsy');
|
|
||||||
if (tipsy) tipsy[options]();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
options = $.extend({}, $.fn.tipsy.defaults, options);
|
|
||||||
|
|
||||||
function get(ele) {
|
|
||||||
var tipsy = $.data(ele, 'tipsy');
|
|
||||||
if (!tipsy) {
|
|
||||||
tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
|
|
||||||
$.data(ele, 'tipsy', tipsy);
|
|
||||||
}
|
|
||||||
return tipsy;
|
|
||||||
}
|
|
||||||
|
|
||||||
function enter() {
|
|
||||||
var tipsy = get(this);
|
|
||||||
tipsy.hoverState = 'in';
|
|
||||||
if (options.delayIn == 0) {
|
|
||||||
tipsy.show();
|
|
||||||
} else {
|
|
||||||
tipsy.fixTitle();
|
|
||||||
setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function leave() {
|
|
||||||
var tipsy = get(this);
|
|
||||||
tipsy.hoverState = 'out';
|
|
||||||
if (options.delayOut == 0) {
|
|
||||||
tipsy.hide();
|
|
||||||
} else {
|
|
||||||
setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options.live) this.each(function() { get(this); });
|
|
||||||
|
|
||||||
if (options.trigger != 'manual') {
|
|
||||||
var binder = options.live ? 'live' : 'bind',
|
|
||||||
eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
|
|
||||||
eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
|
|
||||||
this[binder](eventIn, enter)[binder](eventOut, leave);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.tipsy.clear = function() {
|
|
||||||
$('div.tipsy').stop().remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.tipsy.defaults = {
|
|
||||||
className: null,
|
|
||||||
delayIn: 0,
|
|
||||||
delayOut: 0,
|
|
||||||
fade: false,
|
|
||||||
fallback: '',
|
|
||||||
gravity: 'n',
|
|
||||||
html: false,
|
|
||||||
live: false,
|
|
||||||
offset: 0,
|
|
||||||
opacity: 0.8,
|
|
||||||
title: 'title',
|
|
||||||
trigger: 'hover'
|
|
||||||
};
|
|
||||||
|
|
||||||
// Overwrite this method to provide options on a per-element basis.
|
|
||||||
// For example, you could store the gravity in a 'tipsy-gravity' attribute:
|
|
||||||
// return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
|
|
||||||
// (remember - do not modify 'options' in place!)
|
|
||||||
$.fn.tipsy.elementOptions = function(ele, options) {
|
|
||||||
return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.tipsy.autoNS = function() {
|
|
||||||
return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.tipsy.autoWE = function() {
|
|
||||||
return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* yields a closure of the supplied parameters, producing a function that takes
|
|
||||||
* no arguments and is suitable for use as an autogravity function like so:
|
|
||||||
*
|
|
||||||
* @param margin (int) - distance from the viewable region edge that an
|
|
||||||
* element should be before setting its tooltip's gravity to be away
|
|
||||||
* from that edge.
|
|
||||||
* @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
|
|
||||||
* if there are no viewable region edges effecting the tooltip's
|
|
||||||
* gravity. It will try to vary from this minimally, for example,
|
|
||||||
* if 'sw' is preferred and an element is near the right viewable
|
|
||||||
* region edge, but not the top edge, it will set the gravity for
|
|
||||||
* that element's tooltip to be 'se', preserving the southern
|
|
||||||
* component.
|
|
||||||
*/
|
|
||||||
$.fn.tipsy.autoBounds = function(margin, prefer) {
|
|
||||||
return function() {
|
|
||||||
var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
|
|
||||||
boundTop = $(document).scrollTop() + margin,
|
|
||||||
boundLeft = $(document).scrollLeft() + margin,
|
|
||||||
$this = $(this);
|
|
||||||
|
|
||||||
if ($this.offset().top < boundTop) dir.ns = 'n';
|
|
||||||
if ($this.offset().left < boundLeft) dir.ew = 'w';
|
|
||||||
if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
|
|
||||||
if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';
|
|
||||||
|
|
||||||
return dir.ns + (dir.ew ? dir.ew : '');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
})(jQuery);
|
|
|
@ -1,25 +0,0 @@
|
||||||
.tipsy { font-size: 90%; position: absolute; padding: 5px; z-index: 100000; overflow: hidden;}
|
|
||||||
.tipsy-inner { background-color: #000; color: #FFF; max-width: 500px; padding: 5px 8px 4px 8px; }
|
|
||||||
|
|
||||||
/* Rounded corners */
|
|
||||||
.tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
|
|
||||||
|
|
||||||
/* Uncomment for shadow */
|
|
||||||
.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }
|
|
||||||
|
|
||||||
.tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; }
|
|
||||||
|
|
||||||
/* Rules to colour arrows */
|
|
||||||
.tipsy-arrow-n { border-bottom-color: #000; }
|
|
||||||
.tipsy-arrow-s { border-top-color: #000; }
|
|
||||||
.tipsy-arrow-e { border-left-color: #000; }
|
|
||||||
.tipsy-arrow-w { border-right-color: #000; }
|
|
||||||
|
|
||||||
.tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; }
|
|
||||||
.tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
|
|
||||||
.tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
|
|
||||||
.tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
|
||||||
.tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
|
||||||
.tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
|
||||||
.tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; }
|
|
||||||
.tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; }
|
|
|
@ -506,40 +506,6 @@
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.openerp.oe_tooltip {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.openerp.oe_tooltip .oe_tooltip_string {
|
|
||||||
color: #ffdd55;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
.openerp.oe_tooltip .oe_tooltip_help {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
.openerp.oe_tooltip .oe_tooltip_technical {
|
|
||||||
padding: 0 0 4px 0;
|
|
||||||
margin: 5px 0 0 15px;
|
|
||||||
}
|
|
||||||
.openerp.oe_tooltip .oe_tooltip_technical li {
|
|
||||||
list-style: circle;
|
|
||||||
}
|
|
||||||
.openerp.oe_tooltip .oe_tooltip_technical_title {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.openerp.oe_tooltip .oe_tooltip_close {
|
|
||||||
margin: -5px 0 0 2px;
|
|
||||||
cursor: default;
|
|
||||||
float: right;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.openerp.oe_tooltip .oe_tooltip_close:hover {
|
|
||||||
color: #999999;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.openerp.oe_tooltip .oe_tooltip_message {
|
|
||||||
max-width: 310px;
|
|
||||||
}
|
|
||||||
.openerp .oe_notebook {
|
.openerp .oe_notebook {
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
|
@ -756,7 +722,7 @@
|
||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
}
|
}
|
||||||
.openerp .oe_notification {
|
.openerp .oe_notification {
|
||||||
z-index: 1050;
|
z-index: 1500;
|
||||||
}
|
}
|
||||||
.openerp .oe_webclient_timezone_notification a {
|
.openerp .oe_webclient_timezone_notification a {
|
||||||
color: white;
|
color: white;
|
||||||
|
@ -1926,7 +1892,7 @@
|
||||||
.openerp .oe_form > :not(.oe_form_nosheet) header {
|
.openerp .oe_form > :not(.oe_form_nosheet) header {
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
}
|
}
|
||||||
.openerp .oe_form > :not(.oe_form_nosheet) header ul {
|
.openerp .oe_form > :not(.oe_form_nosheet) header ul:not(.oe_tooltip_technical):not(.oe_dropdown_menu) {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
@ -2778,13 +2744,15 @@
|
||||||
padding: 3px 6px;
|
padding: 3px 6px;
|
||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
}
|
}
|
||||||
.openerp .oe_list_content > tbody > tr > td > button.btn_img, .openerp .oe_list_content > tbody > tr > th > button.btn_img {
|
.openerp .oe_list_content > tbody > tr > td > button, .openerp .oe_list_content > tbody > tr > th > button {
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
-moz-box-shadow: none;
|
}
|
||||||
-webkit-box-shadow: none;
|
.openerp .oe_list_content > tbody > tr > td > button.btn_txt, .openerp .oe_list_content > tbody > tr > th > button.btn_txt {
|
||||||
box-shadow: none;
|
border: 1px solid rgba(0, 0, 0, 0.4);
|
||||||
|
background: #e3e3e3;
|
||||||
|
padding: 3px 12px;
|
||||||
}
|
}
|
||||||
.openerp .oe_list_content > tbody > tr > td.oe_list_checkbox:first-child, .openerp .oe_list_content > tbody > tr th.oe_list_checkbox:first-child {
|
.openerp .oe_list_content > tbody > tr > td.oe_list_checkbox:first-child, .openerp .oe_list_content > tbody > tr th.oe_list_checkbox:first-child {
|
||||||
width: 17px;
|
width: 17px;
|
||||||
|
@ -3329,6 +3297,52 @@ body.oe_single_form .oe_single_form_container {
|
||||||
overflow: hidden !important;
|
overflow: hidden !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.tooltip {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif;
|
||||||
|
color: #4c4c4c;
|
||||||
|
font-size: 12px;
|
||||||
|
background: white;
|
||||||
|
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-inner {
|
||||||
|
text-align: left !important;
|
||||||
|
max-width: 350px;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-inner .oe_tooltip_string {
|
||||||
|
color: #ffdd55;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-inner .oe_tooltip_help {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-inner .oe_tooltip_technical {
|
||||||
|
padding: 0 0 4px 0;
|
||||||
|
margin: 5px 0 0 15px;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-inner .oe_tooltip_technical li {
|
||||||
|
list-style: circle;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-inner .oe_tooltip_technical_title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-inner .oe_tooltip_close {
|
||||||
|
margin: -5px 0 0 2px;
|
||||||
|
cursor: default;
|
||||||
|
float: right;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-inner .oe_tooltip_close:hover {
|
||||||
|
color: #999999;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.tooltip .tooltip-inner .oe_tooltip_message {
|
||||||
|
max-width: 310px;
|
||||||
|
}
|
||||||
|
|
||||||
.ui-icon {
|
.ui-icon {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
|
@ -3351,6 +3365,10 @@ body.oe_single_form .oe_single_form_container {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-datepicker {
|
||||||
|
z-index: 1500 !important;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="radio"], input[type="checkbox"] {
|
input[type="radio"], input[type="checkbox"] {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
|
|
|
@ -473,33 +473,6 @@ $sheet-padding: 16px
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
margin-bottom: 1px
|
margin-bottom: 1px
|
||||||
// }}}
|
// }}}
|
||||||
// Tooltips {{{
|
|
||||||
&.oe_tooltip
|
|
||||||
font-size: 12px
|
|
||||||
.oe_tooltip_string
|
|
||||||
color: #FD5
|
|
||||||
font-weight: bold
|
|
||||||
font-size: 13px
|
|
||||||
.oe_tooltip_help
|
|
||||||
white-space: pre-wrap
|
|
||||||
.oe_tooltip_technical
|
|
||||||
padding: 0 0 4px 0
|
|
||||||
margin: 5px 0 0 15px
|
|
||||||
li
|
|
||||||
list-style: circle
|
|
||||||
.oe_tooltip_technical_title
|
|
||||||
font-weight: bold
|
|
||||||
.oe_tooltip_close
|
|
||||||
margin: -5px 0 0 2px
|
|
||||||
cursor: default
|
|
||||||
float: right
|
|
||||||
color: white
|
|
||||||
&:hover
|
|
||||||
color: #999
|
|
||||||
cursor: pointer
|
|
||||||
.oe_tooltip_message
|
|
||||||
max-width: 310px
|
|
||||||
// }}}
|
|
||||||
// Notebook {{{
|
// Notebook {{{
|
||||||
.oe_notebook
|
.oe_notebook
|
||||||
margin: 8px 0
|
margin: 8px 0
|
||||||
|
@ -667,7 +640,8 @@ $sheet-padding: 16px
|
||||||
// }}}
|
// }}}
|
||||||
// Notifications {{{
|
// Notifications {{{
|
||||||
.oe_notification
|
.oe_notification
|
||||||
z-index: 1050
|
z-index: 1500
|
||||||
|
|
||||||
.oe_webclient_timezone_notification
|
.oe_webclient_timezone_notification
|
||||||
a
|
a
|
||||||
color: white
|
color: white
|
||||||
|
@ -1578,7 +1552,7 @@ $sheet-padding: 16px
|
||||||
// FormView.header {{{
|
// FormView.header {{{
|
||||||
.oe_form > :not(.oe_form_nosheet) header
|
.oe_form > :not(.oe_form_nosheet) header
|
||||||
padding-left: 2px
|
padding-left: 2px
|
||||||
ul
|
ul:not(.oe_tooltip_technical):not(.oe_dropdown_menu)
|
||||||
display: inline-block
|
display: inline-block
|
||||||
float: right
|
float: right
|
||||||
.oe_button
|
.oe_button
|
||||||
|
@ -2248,11 +2222,14 @@ $sheet-padding: 16px
|
||||||
padding: 3px 6px
|
padding: 3px 6px
|
||||||
white-space: pre-line
|
white-space: pre-line
|
||||||
> td, > th
|
> td, > th
|
||||||
> button.btn_img
|
> button
|
||||||
border: none
|
border: none
|
||||||
background: transparent
|
background: transparent
|
||||||
padding: 0
|
padding: 0
|
||||||
@include box-shadow(none)
|
> button.btn_txt
|
||||||
|
border: 1px solid rgba(0,0,0,0.4)
|
||||||
|
background: #e3e3e3
|
||||||
|
padding: 3px 12px
|
||||||
> td.oe_list_checkbox:first-child, th.oe_list_checkbox:first-child
|
> td.oe_list_checkbox:first-child, th.oe_list_checkbox:first-child
|
||||||
width: 17px
|
width: 17px
|
||||||
&:after
|
&:after
|
||||||
|
@ -2704,6 +2681,44 @@ body.oe_single_form
|
||||||
overflow: hidden !important
|
overflow: hidden !important
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
|
// End of customize
|
||||||
|
|
||||||
|
// Customize bootstrap3 for tooltip
|
||||||
|
.tooltip
|
||||||
|
padding: 0
|
||||||
|
margin: 0
|
||||||
|
font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif
|
||||||
|
color: #4c4c4c
|
||||||
|
font-size: 12px
|
||||||
|
background: white
|
||||||
|
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5)
|
||||||
|
background-color: transparent
|
||||||
|
.tooltip-inner
|
||||||
|
text-align: left !important
|
||||||
|
max-width: 350px
|
||||||
|
.oe_tooltip_string
|
||||||
|
color: #FD5
|
||||||
|
font-weight: bold
|
||||||
|
font-size: 13px
|
||||||
|
.oe_tooltip_help
|
||||||
|
white-space: pre-wrap
|
||||||
|
.oe_tooltip_technical
|
||||||
|
padding: 0 0 4px 0
|
||||||
|
margin: 5px 0 0 15px
|
||||||
|
li
|
||||||
|
list-style: circle
|
||||||
|
.oe_tooltip_technical_title
|
||||||
|
font-weight: bold
|
||||||
|
.oe_tooltip_close
|
||||||
|
margin: -5px 0 0 2px
|
||||||
|
cursor: default
|
||||||
|
float: right
|
||||||
|
color: white
|
||||||
|
&:hover
|
||||||
|
color: #999
|
||||||
|
cursor: pointer
|
||||||
|
.oe_tooltip_message
|
||||||
|
max-width: 310px
|
||||||
|
|
||||||
// Hack for ui icon {{{
|
// Hack for ui icon {{{
|
||||||
.ui-icon
|
.ui-icon
|
||||||
|
@ -2726,6 +2741,9 @@ body.oe_single_form
|
||||||
.oe_act_window.modal-body
|
.oe_act_window.modal-body
|
||||||
padding: 0
|
padding: 0
|
||||||
|
|
||||||
|
.ui-datepicker
|
||||||
|
z-index: 1500 !important
|
||||||
|
|
||||||
input[type="radio"], input[type="checkbox"]
|
input[type="radio"], input[type="checkbox"]
|
||||||
margin-right: 4px
|
margin-right: 4px
|
||||||
margin-left: 4px
|
margin-left: 4px
|
||||||
|
|
|
@ -1078,8 +1078,8 @@ instance.web.Client = instance.web.Widget.extend({
|
||||||
},
|
},
|
||||||
bind_events: function() {
|
bind_events: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.$el.on('mouseenter', '.oe_systray > div:not([data-tipsy=true])', function() {
|
this.$el.on('mouseenter', '.oe_systray > div:not([data-toggle=tooltip])', function() {
|
||||||
$(this).attr('data-tipsy', 'true').tipsy().trigger('mouseenter');
|
$(this).attr('data-toggle', 'tooltip').tooltip().trigger('mouseenter');
|
||||||
});
|
});
|
||||||
this.$el.on('click', '.oe_dropdown_toggle', function(ev) {
|
this.$el.on('click', '.oe_dropdown_toggle', function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
@ -1103,7 +1103,7 @@ instance.web.Client = instance.web.Widget.extend({
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
instance.web.bus.on('click', this, function(ev) {
|
instance.web.bus.on('click', this, function(ev) {
|
||||||
$.fn.tipsy.clear();
|
$.fn.tooltip('destroy');
|
||||||
if (!$(ev.target).is('input[type=file]')) {
|
if (!$(ev.target).is('input[type=file]')) {
|
||||||
self.$el.find('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened');
|
self.$el.find('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened');
|
||||||
}
|
}
|
||||||
|
@ -1457,7 +1457,7 @@ instance.web.embed = function (origin, dbname, login, key, action, options) {
|
||||||
$('head').append($('<link>', {
|
$('head').append($('<link>', {
|
||||||
'rel': 'stylesheet',
|
'rel': 'stylesheet',
|
||||||
'type': 'text/css',
|
'type': 'text/css',
|
||||||
'href': origin +'/web/webclient/css'
|
'href': origin +'/web/css/web.assets_webclient'
|
||||||
}));
|
}));
|
||||||
var currentScript = document.currentScript;
|
var currentScript = document.currentScript;
|
||||||
if (!currentScript) {
|
if (!currentScript) {
|
||||||
|
|
|
@ -232,7 +232,7 @@ instance.web.Session.include( /** @lends instance.web.Session# */{
|
||||||
var self = this;
|
var self = this;
|
||||||
return this.session_reload().then(function(result) {
|
return this.session_reload().then(function(result) {
|
||||||
var modules = instance._modules.join(',');
|
var modules = instance._modules.join(',');
|
||||||
var deferred = self.rpc('/web/webclient/qweblist', {mods: modules}).then(self.load_qweb.bind(self));
|
var deferred = self.load_qweb(modules);
|
||||||
if(self.session_is_valid()) {
|
if(self.session_is_valid()) {
|
||||||
return deferred.then(function() { return self.load_modules(); });
|
return deferred.then(function() { return self.load_modules(); });
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,7 @@ instance.web.Session.include( /** @lends instance.web.Session# */{
|
||||||
loaded = $.when(
|
loaded = $.when(
|
||||||
loaded,
|
loaded,
|
||||||
self.rpc('/web/webclient/csslist', {mods: to_load}).done(self.load_css.bind(self)),
|
self.rpc('/web/webclient/csslist', {mods: to_load}).done(self.load_css.bind(self)),
|
||||||
self.rpc('/web/webclient/qweblist', {mods: to_load}).then(self.load_qweb.bind(self)),
|
self.load_qweb(to_load),
|
||||||
self.rpc('/web/webclient/jslist', {mods: to_load}).done(function(files) {
|
self.rpc('/web/webclient/jslist', {mods: to_load}).done(function(files) {
|
||||||
file_list = file_list.concat(files);
|
file_list = file_list.concat(files);
|
||||||
})
|
})
|
||||||
|
@ -375,14 +375,12 @@ instance.web.Session.include( /** @lends instance.web.Session# */{
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
},
|
},
|
||||||
load_qweb: function(files) {
|
load_qweb: function(mods) {
|
||||||
var self = this;
|
var self = this;
|
||||||
_.each(files, function(file) {
|
self.qweb_mutex.exec(function() {
|
||||||
self.qweb_mutex.exec(function() {
|
return self.rpc('/web/proxy/load', {path: '/web/webclient/qweb?mods=' + mods}).then(function(xml) {
|
||||||
return self.rpc('/web/proxy/load', {path: file}).then(function(xml) {
|
if (!xml) { return; }
|
||||||
if (!xml) { return; }
|
instance.web.qweb.add_template(_.str.trim(xml));
|
||||||
instance.web.qweb.add_template(_.str.trim(xml));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return self.qweb_mutex.def;
|
return self.qweb_mutex.def;
|
||||||
|
@ -460,14 +458,11 @@ instance.web.Session.include( /** @lends instance.web.Session# */{
|
||||||
.appendTo(document.body)
|
.appendTo(document.body)
|
||||||
.load(function () {
|
.load(function () {
|
||||||
try {
|
try {
|
||||||
if (options.error) {
|
if (options.error) {
|
||||||
if (!this.contentDocument.body.childNodes[1]) {
|
var body = this.contentDocument.body;
|
||||||
options.error(this.contentDocument.body.childNodes);
|
var node = body.childNodes[1] || body.childNodes[0];
|
||||||
}
|
options.error(JSON.parse(node.textContent));
|
||||||
else {
|
}
|
||||||
options.error(JSON.parse(this.contentDocument.body.childNodes[1].textContent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
complete();
|
complete();
|
||||||
}
|
}
|
||||||
|
@ -788,6 +783,22 @@ instance.web.unblockUI = function() {
|
||||||
return $.unblockUI.apply($, arguments);
|
return $.unblockUI.apply($, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Bootstrap defaults overwrite */
|
||||||
|
$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top';
|
||||||
|
$.fn.tooltip.Constructor.DEFAULTS.html = true;
|
||||||
|
$.fn.tooltip.Constructor.DEFAULTS.container = 'body';
|
||||||
|
//overwrite bootstrap tooltip method to fix bug when using placement
|
||||||
|
//auto and the parent element does not exist anymore resulting in
|
||||||
|
//an error. This should be remove once bootstrap fix the bug
|
||||||
|
var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show;
|
||||||
|
$.fn.tooltip.Constructor.prototype.show = function (e) {
|
||||||
|
if (this.$element.parent().length === 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return bootstrap_show_function.call(this, e);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registry for all the client actions key: tag value: widget
|
* Registry for all the client actions key: tag value: widget
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -32,7 +32,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
||||||
var self = this;
|
var self = this;
|
||||||
var options = {
|
var options = {
|
||||||
buttons: [
|
buttons: [
|
||||||
{text: _t("Close"), click: function () { self.close(); }},
|
{text: _t("Close"), click: function () { self.$el.parents('.modal').modal('hide'); }},
|
||||||
{text: _t("Export To File"), click: function () { self.on_click_export_data(); }}
|
{text: _t("Export To File"), click: function () { self.on_click_export_data(); }}
|
||||||
],
|
],
|
||||||
close: function () { self.close();}
|
close: function () { self.close();}
|
||||||
|
|
|
@ -29,8 +29,8 @@ my.Facet = B.Model.extend({
|
||||||
B.Model.prototype.initialize.apply(this, arguments);
|
B.Model.prototype.initialize.apply(this, arguments);
|
||||||
|
|
||||||
this.values = new my.FacetValues(values || []);
|
this.values = new my.FacetValues(values || []);
|
||||||
this.values.on('add remove change reset', function () {
|
this.values.on('add remove change reset', function (_, options) {
|
||||||
this.trigger('change', this);
|
this.trigger('change', this, options);
|
||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
get: function (key) {
|
get: function (key) {
|
||||||
|
@ -399,7 +399,8 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
||||||
this.setup_global_completion();
|
this.setup_global_completion();
|
||||||
this.query = new my.SearchQuery()
|
this.query = new my.SearchQuery()
|
||||||
.on('add change reset remove', this.proxy('do_search'))
|
.on('add change reset remove', this.proxy('do_search'))
|
||||||
.on('add change reset remove', this.proxy('renderFacets'));
|
.on('change', this.proxy('renderChangedFacets'))
|
||||||
|
.on('add reset remove', this.proxy('renderFacets'));
|
||||||
|
|
||||||
if (this.options.hidden) {
|
if (this.options.hidden) {
|
||||||
this.$el.hide();
|
this.$el.hide();
|
||||||
|
@ -578,14 +579,20 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
||||||
.trigger('blur');
|
.trigger('blur');
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
* Call the renderFacets method with the correct arguments.
|
||||||
* @param {openerp.web.search.SearchQuery | openerp.web.search.Facet} _1
|
* This is due to the fact that change events are called with two arguments
|
||||||
* @param {openerp.web.search.Facet} [_2]
|
* (model, options) while add, reset and remove events are called with
|
||||||
|
* (collection, model, options) as arguments
|
||||||
|
*/
|
||||||
|
renderChangedFacets: function (model, options) {
|
||||||
|
this.renderFacets(undefined, model, options);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @param {openerp.web.search.SearchQuery | undefined} Undefined if event is change
|
||||||
|
* @param {openerp.web.search.Facet}
|
||||||
* @param {Object} [options]
|
* @param {Object} [options]
|
||||||
*/
|
*/
|
||||||
renderFacets: function (_1, _2, options) {
|
renderFacets: function (collection, model, options) {
|
||||||
// _1: model if event=change, otherwise collection
|
|
||||||
// _2: undefined if event=change, otherwise model
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var started = [];
|
var started = [];
|
||||||
var $e = this.$('div.oe_searchview_facets');
|
var $e = this.$('div.oe_searchview_facets');
|
||||||
|
@ -610,6 +617,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
||||||
});
|
});
|
||||||
|
|
||||||
$.when.apply(null, started).then(function () {
|
$.when.apply(null, started).then(function () {
|
||||||
|
if (options && options.focus_input === false) return;
|
||||||
var input_to_focus;
|
var input_to_focus;
|
||||||
// options.at: facet inserted at given index, focus next input
|
// options.at: facet inserted at given index, focus next input
|
||||||
// otherwise just focus last input
|
// otherwise just focus last input
|
||||||
|
@ -618,7 +626,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
||||||
} else {
|
} else {
|
||||||
input_to_focus = self.input_subviews[(options.at + 1) * 2];
|
input_to_focus = self.input_subviews[(options.at + 1) * 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
input_to_focus.$el.focus();
|
input_to_focus.$el.focus();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1602,8 +1609,11 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
||||||
return facetValue.get('label');
|
return facetValue.get('label');
|
||||||
},
|
},
|
||||||
make_domain: function (name, operator, facetValue) {
|
make_domain: function (name, operator, facetValue) {
|
||||||
if (operator === this.default_operator) {
|
switch(operator){
|
||||||
|
case this.default_operator:
|
||||||
return [[name, '=', facetValue.get('value')]];
|
return [[name, '=', facetValue.get('value')]];
|
||||||
|
case 'child_of':
|
||||||
|
return [[name, 'child_of', facetValue.get('value')]];
|
||||||
}
|
}
|
||||||
return this._super(name, operator, facetValue);
|
return this._super(name, operator, facetValue);
|
||||||
},
|
},
|
||||||
|
|
|
@ -48,15 +48,6 @@ openerp.testing = {};
|
||||||
|
|
||||||
testing.dependencies = window['oe_all_dependencies'] || [];
|
testing.dependencies = window['oe_all_dependencies'] || [];
|
||||||
testing.current_module = null;
|
testing.current_module = null;
|
||||||
testing.templates = { };
|
|
||||||
testing.add_template = function (name) {
|
|
||||||
var xhr = QWeb2.Engine.prototype.get_xhr();
|
|
||||||
xhr.open('GET', name, false);
|
|
||||||
xhr.send(null);
|
|
||||||
(testing.templates[testing.current_module] =
|
|
||||||
testing.templates[testing.current_module] || [])
|
|
||||||
.push(xhr.responseXML);
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* Function which does not do anything
|
* Function which does not do anything
|
||||||
*/
|
*/
|
||||||
|
@ -206,7 +197,7 @@ openerp.testing = {};
|
||||||
teardown: testing.noop
|
teardown: testing.noop
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.module(testing.current_module + '.' + name, {_oe: options});
|
QUnit.module(name, {_oe: options});
|
||||||
body(testing['case']);
|
body(testing['case']);
|
||||||
};
|
};
|
||||||
testing['case'] = function (name, options, callback) {
|
testing['case'] = function (name, options, callback) {
|
||||||
|
@ -244,18 +235,6 @@ openerp.testing = {};
|
||||||
expect(opts.asserts);
|
expect(opts.asserts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.templates) {
|
|
||||||
for(var i=0; i<module_deps.length; ++i) {
|
|
||||||
var dep = module_deps[i];
|
|
||||||
var templates = testing.templates[dep];
|
|
||||||
if (_.isEmpty(templates)) { continue; }
|
|
||||||
|
|
||||||
for (var j=0; j < templates.length; ++j) {
|
|
||||||
instance.web.qweb.add_template(templates[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var $fixture = $('#qunit-fixture');
|
var $fixture = $('#qunit-fixture');
|
||||||
|
|
||||||
var mock, async = false;
|
var mock, async = false;
|
||||||
|
|
|
@ -730,8 +730,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
on_button_save: function() {
|
on_button_save: function(e) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
$(e.target).attr("disabled", true);
|
||||||
return this.save().done(function(result) {
|
return this.save().done(function(result) {
|
||||||
self.trigger("save", result);
|
self.trigger("save", result);
|
||||||
self.reload().then(function() {
|
self.reload().then(function() {
|
||||||
|
@ -741,6 +742,8 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
||||||
parent.menu.do_reload_needaction();
|
parent.menu.do_reload_needaction();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}).always(function(){
|
||||||
|
$(e.target).attr("disabled", false);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
on_button_cancel: function(event) {
|
on_button_cancel: function(event) {
|
||||||
|
@ -1835,7 +1838,7 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
|
||||||
this.$el.addClass(this.node.attrs["class"] || "");
|
this.$el.addClass(this.node.attrs["class"] || "");
|
||||||
},
|
},
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
$.fn.tipsy.clear();
|
$.fn.tooltip('destroy');
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
@ -1866,10 +1869,25 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
|
||||||
do_attach_tooltip: function(widget, trigger, options) {
|
do_attach_tooltip: function(widget, trigger, options) {
|
||||||
widget = widget || this;
|
widget = widget || this;
|
||||||
trigger = trigger || this.$el;
|
trigger = trigger || this.$el;
|
||||||
|
var container = 'body';
|
||||||
|
/*TODO: need to be refactor
|
||||||
|
in the case we can find the view form in the parent,
|
||||||
|
attach the element to it (to prevent tooltip to keep showing
|
||||||
|
when switching view) or if we have a modal currently showing,
|
||||||
|
attach tooltip to the modal to prevent the tooltip to show in the body in the
|
||||||
|
case we close the modal too fast*/
|
||||||
|
if ($(trigger).parents('.oe_view_manager_view_form').length > 0){
|
||||||
|
container = $(trigger).parents('.oe_view_manager_view_form');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (window.$('.modal.in').length>0){
|
||||||
|
container = window.$('.modal.in:last()');
|
||||||
|
}
|
||||||
|
}
|
||||||
options = _.extend({
|
options = _.extend({
|
||||||
delayIn: 500,
|
delay: { show: 500, hide: 0 },
|
||||||
delayOut: 0,
|
trigger: 'hover',
|
||||||
fade: true,
|
container: container,
|
||||||
title: function() {
|
title: function() {
|
||||||
var template = widget.template + '.tooltip';
|
var template = widget.template + '.tooltip';
|
||||||
if (!QWeb.has_template(template)) {
|
if (!QWeb.has_template(template)) {
|
||||||
|
@ -1880,12 +1898,12 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
|
||||||
widget: widget
|
widget: widget
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
gravity: $.fn.tipsy.autoBounds(50, 'nw'),
|
|
||||||
html: true,
|
|
||||||
opacity: 0.85,
|
|
||||||
trigger: 'hover'
|
|
||||||
}, options || {});
|
}, options || {});
|
||||||
$(trigger).tipsy(options);
|
//only show tooltip if we are in debug or if we have a help to show, otherwise it will display
|
||||||
|
//as empty
|
||||||
|
if (instance.session.debug || widget.node.attrs.help || (widget.field && widget.field.help)){
|
||||||
|
$(trigger).tooltip(options);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Builds a new context usable for operations related to fields by merging
|
* Builds a new context usable for operations related to fields by merging
|
||||||
|
@ -2122,8 +2140,8 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w
|
||||||
this.$el.find('.oe_field_translate').click(this.on_translate);
|
this.$el.find('.oe_field_translate').click(this.on_translate);
|
||||||
}
|
}
|
||||||
this.$label = this.view ? this.view.$el.find('label[for=' + this.id_for_label + ']') : $();
|
this.$label = this.view ? this.view.$el.find('label[for=' + this.id_for_label + ']') : $();
|
||||||
|
this.do_attach_tooltip(this, this.$label[0] || this.$el);
|
||||||
if (instance.session.debug) {
|
if (instance.session.debug) {
|
||||||
this.do_attach_tooltip(this, this.$label[0] || this.$el);
|
|
||||||
this.$label.off('dblclick').on('dblclick', function() {
|
this.$label.off('dblclick').on('dblclick', function() {
|
||||||
console.log("Field '%s' of type '%s' in View: %o", self.name, (self.node.attrs.widget || self.field.type), self.view);
|
console.log("Field '%s' of type '%s' in View: %o", self.name, (self.node.attrs.widget || self.field.type), self.view);
|
||||||
window.w = self;
|
window.w = self;
|
||||||
|
@ -3338,13 +3356,16 @@ instance.web.form.CompletionFieldMixin = {
|
||||||
instance.web.form.M2ODialog = instance.web.Dialog.extend({
|
instance.web.form.M2ODialog = instance.web.Dialog.extend({
|
||||||
template: "M2ODialog",
|
template: "M2ODialog",
|
||||||
init: function(parent) {
|
init: function(parent) {
|
||||||
|
this.name = parent.string;
|
||||||
this._super(parent, {
|
this._super(parent, {
|
||||||
title: _.str.sprintf(_t("Add %s"), parent.string),
|
title: _.str.sprintf(_t("Create a %s"), parent.string),
|
||||||
size: 'medium',
|
size: 'medium',
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
start: function() {
|
start: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var text = _.str.sprintf(_t("You are creating a new %s, are you sure it does not exist yet?"), self.name);
|
||||||
|
this.$("p").text( text );
|
||||||
this.$buttons.html(QWeb.render("M2ODialog.buttons"));
|
this.$buttons.html(QWeb.render("M2ODialog.buttons"));
|
||||||
this.$("input").val(this.getParent().last_query);
|
this.$("input").val(this.getParent().last_query);
|
||||||
this.$buttons.find(".oe_form_m2o_qc_button").click(function(){
|
this.$buttons.find(".oe_form_m2o_qc_button").click(function(){
|
||||||
|
@ -3468,7 +3489,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
||||||
self.display_value_backup = {};
|
self.display_value_backup = {};
|
||||||
self.render_value();
|
self.render_value();
|
||||||
self.focus();
|
self.focus();
|
||||||
self.view.do_onchange(self);
|
self.trigger('changed_value');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3603,6 +3624,8 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
||||||
minLength: 0,
|
minLength: 0,
|
||||||
delay: 250
|
delay: 250
|
||||||
});
|
});
|
||||||
|
// set position for list of suggestions box
|
||||||
|
this.$input.autocomplete( "option", "position", { my : "left top", at: "left bottom" } );
|
||||||
this.$input.autocomplete("widget").openerpClass();
|
this.$input.autocomplete("widget").openerpClass();
|
||||||
// used to correct a bug when selecting an element by pushing 'enter' in an editable list
|
// used to correct a bug when selecting an element by pushing 'enter' in an editable list
|
||||||
this.$input.keyup(function(e) {
|
this.$input.keyup(function(e) {
|
||||||
|
|
|
@ -581,7 +581,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
|
||||||
var self = this;
|
var self = this;
|
||||||
this.$el.find('.oe_view_manager_switch a').click(function() {
|
this.$el.find('.oe_view_manager_switch a').click(function() {
|
||||||
self.switch_mode($(this).data('view-type'));
|
self.switch_mode($(this).data('view-type'));
|
||||||
}).tipsy();
|
}).tooltip();
|
||||||
var views_ids = {};
|
var views_ids = {};
|
||||||
_.each(this.views_src, function(view) {
|
_.each(this.views_src, function(view) {
|
||||||
self.views[view.view_type] = $.extend({}, view, {
|
self.views[view.view_type] = $.extend({}, view, {
|
||||||
|
@ -1157,10 +1157,8 @@ instance.web.Sidebar = instance.web.Widget.extend({
|
||||||
this.$('.oe_form_dropdown_section').each(function() {
|
this.$('.oe_form_dropdown_section').each(function() {
|
||||||
$(this).toggle(!!$(this).find('li').length);
|
$(this).toggle(!!$(this).find('li').length);
|
||||||
});
|
});
|
||||||
|
self.$("[title]").tooltip({
|
||||||
self.$("[title]").tipsy({
|
delay: { show: 500, hide: 0}
|
||||||
'html': true,
|
|
||||||
'delayIn': 500,
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<h3 class="modal-title"><t t-raw="title"/></h3>
|
<h3 class="modal-title"><t t-raw="title"/></h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body" style="overflow-y: auto;">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -800,12 +800,11 @@
|
||||||
</t>
|
</t>
|
||||||
<button t-name="ListView.row.text_button" type="button"
|
<button t-name="ListView.row.text_button" type="button"
|
||||||
t-att-title="widget.string" t-att-disabled="disabled || undefined"
|
t-att-title="widget.string" t-att-disabled="disabled || undefined"
|
||||||
t-att-class="disabled ? 'oe_list_button_disabled btn' : 'btn'">
|
t-att-class="disabled ? 'oe_list_button_disabled btn_txt oe_link' : 'btn_txt oe_link'"
|
||||||
<t t-esc="widget.string"/>
|
><t t-esc="widget.string"/></button>
|
||||||
</button>
|
|
||||||
<button t-name="ListView.row.button" type="button"
|
<button t-name="ListView.row.button" type="button"
|
||||||
t-att-title="widget.string" t-att-disabled="disabled || undefined"
|
t-att-title="widget.string" t-att-disabled="disabled || undefined"
|
||||||
t-att-class="disabled ? 'oe_list_button_disabled btn_img' : 'btn_img'"
|
t-att-class="disabled ? 'oe_list_button_disabled' : ''"
|
||||||
><img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png"
|
><img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png"
|
||||||
t-att-alt="widget.string"/></button>
|
t-att-alt="widget.string"/></button>
|
||||||
<t t-extend="ListView.row">
|
<t t-extend="ListView.row">
|
||||||
|
@ -943,7 +942,6 @@
|
||||||
</t>
|
</t>
|
||||||
<t t-name="FormRenderingLabel">
|
<t t-name="FormRenderingLabel">
|
||||||
<label t-att-for="_for"
|
<label t-att-for="_for"
|
||||||
t-att-title="help"
|
|
||||||
t-attf-class="#{classnames} oe_form_label#{help ? '_help' : ''} oe_align_#{align}">
|
t-attf-class="#{classnames} oe_form_label#{help ? '_help' : ''} oe_align_#{align}">
|
||||||
<t t-esc="string"/>
|
<t t-esc="string"/>
|
||||||
</label>
|
</label>
|
||||||
|
@ -1005,7 +1003,7 @@
|
||||||
</li>
|
</li>
|
||||||
<li t-if="widget.field and widget.field.selection" data-item="selection">
|
<li t-if="widget.field and widget.field.selection" data-item="selection">
|
||||||
<span class="oe_tooltip_technical_title">Selection:</span>
|
<span class="oe_tooltip_technical_title">Selection:</span>
|
||||||
<ul>
|
<ul class="oe_tooltip_technical">
|
||||||
<li t-foreach="widget.field.selection" t-as="option">
|
<li t-foreach="widget.field.selection" t-as="option">
|
||||||
[<t t-esc="option[0]"/>]
|
[<t t-esc="option[0]"/>]
|
||||||
<t t-if="option[1]"> - </t>
|
<t t-if="option[1]"> - </t>
|
||||||
|
@ -1949,13 +1947,14 @@
|
||||||
</t>
|
</t>
|
||||||
<t t-name="M2ODialog">
|
<t t-name="M2ODialog">
|
||||||
<div>
|
<div>
|
||||||
|
<p class="oe_grey"/>
|
||||||
Name: <input class="oe_form_m2o_input_name" type="text"/>
|
Name: <input class="oe_form_m2o_input_name" type="text"/>
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
<t t-name="M2ODialog.buttons">
|
<t t-name="M2ODialog.buttons">
|
||||||
<button class="oe_form_m2o_qc_button oe_button oe_highlight">Quick Add</button>
|
<button class="oe_form_m2o_qc_button oe_button oe_highlight">Create</button>
|
||||||
<button class="oe_form_m2o_sc_button oe_button">Add All Info...</button>
|
<button class="oe_form_m2o_sc_button oe_button">Create and edit</button> or
|
||||||
<button class="oe_form_m2o_cancel_button oe_button">Cancel</button>
|
<button class="oe_form_m2o_cancel_button oe_button oe_link"><span>Cancel</span></button>
|
||||||
</t>
|
</t>
|
||||||
<t t-name="FieldMonetary" t-extend="FieldChar">
|
<t t-name="FieldMonetary" t-extend="FieldChar">
|
||||||
<t t-jquery="t:first" t-operation="before">
|
<t t-jquery="t:first" t-operation="before">
|
||||||
|
|
|
@ -361,8 +361,8 @@ openerp.testing.section('list.edition.onwrite', {
|
||||||
strictEqual(
|
strictEqual(
|
||||||
$fix.find('tbody tr:eq(1)').css('color'), 'rgb(255, 0, 0)',
|
$fix.find('tbody tr:eq(1)').css('color'), 'rgb(255, 0, 0)',
|
||||||
'shoud have color applied');
|
'shoud have color applied');
|
||||||
strictEqual(
|
notStrictEqual(
|
||||||
$fix.find('tbody tr:eq(2)').css('color'), 'rgb(0, 0, 0)',
|
$fix.find('tbody tr:eq(2)').css('color'), 'rgb(255, 0, 0)',
|
||||||
'should have default color applied');
|
'should have default color applied');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,4 +2,3 @@
|
||||||
import test_js
|
import test_js
|
||||||
import test_menu
|
import test_menu
|
||||||
import test_serving_base
|
import test_serving_base
|
||||||
import test_ui
|
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
QUnitSuite is a ``unittest.TestSuite`` able to run QUnit_ test suites
|
|
||||||
within the normal unittest process, through PhantomJS_.
|
|
||||||
|
|
||||||
QUnitSuite is built upon `Ben Alman`_'s work of for the interfacing
|
|
||||||
between PhantomJS_ and the host/reporting code: the shims and the
|
|
||||||
PhantomJS_ configuration files are those of grunt_'s ``qunit`` task.
|
|
||||||
|
|
||||||
Why
|
|
||||||
---
|
|
||||||
|
|
||||||
You're a Python shop or developer, you have tools and tests built
|
|
||||||
around unittest (or compatible with unittests) and your testing
|
|
||||||
pipeline is predicated upon that, you're doing web development of some
|
|
||||||
sort these days (as so many are) and you'd like to do some testing of
|
|
||||||
your web stuff.
|
|
||||||
|
|
||||||
But you don't really want to redo your whole testing stack just for
|
|
||||||
that.
|
|
||||||
|
|
||||||
QUnitSuite simply grafts QUnit_-based tests, run in PhantomJS_, in
|
|
||||||
your existing ``unittest``-based architecture.
|
|
||||||
|
|
||||||
What
|
|
||||||
----
|
|
||||||
|
|
||||||
QUnitSuite currently provides a single object as part of its API:
|
|
||||||
``qunitsuite.QUnitSuite(testfile[, timeout])``.
|
|
||||||
|
|
||||||
This produces a ``unittest.TestSuite`` suitable for all the usual
|
|
||||||
stuff (running it, and giving it to an other test suite which will run
|
|
||||||
it, that is).
|
|
||||||
|
|
||||||
``testfile`` is the HTML file bootstrapping your qunit tests, as would
|
|
||||||
usually be accessed via a browser. It can be either a local
|
|
||||||
(``file:``) url, or an HTTP one. As long as a regular browser can open
|
|
||||||
and execute it, PhantomJS_ will manage.
|
|
||||||
|
|
||||||
``timeout`` is a check passed to the PhantomJS_ runner: if the runner
|
|
||||||
produces no information for longer than ``timeout`` milliseconds, the
|
|
||||||
run will be cancelled and a test error will be generated. This
|
|
||||||
situation usually means either your ``testfile`` is not a qunit test
|
|
||||||
file, qunit is not running or qunit's runner was stopped (for an async
|
|
||||||
test) and never restarted.
|
|
||||||
|
|
||||||
The default value is very conservative, most tests should run
|
|
||||||
correctly with lower timeouts (especially if all tests are
|
|
||||||
synchronous).
|
|
||||||
|
|
||||||
How
|
|
||||||
---
|
|
||||||
|
|
||||||
``unittest``'s autodiscovery protocol does not directly work with test
|
|
||||||
suites (it looks for test cases). If you want autodiscovery to work
|
|
||||||
correctly, you will have to use the ``load_tests`` protocol::
|
|
||||||
|
|
||||||
# in a testing module
|
|
||||||
def load_tests(loader, tests, pattern):
|
|
||||||
tests.addTest(QUnitSuite(qunit_test_path.html))
|
|
||||||
return tests
|
|
||||||
|
|
||||||
outside of that specific case, you can use a ``QUnitSuite`` as a
|
|
||||||
standard ``TestSuite`` instance, running it, adding it to an other
|
|
||||||
suite or passing it to a ``TestRunner``
|
|
||||||
|
|
||||||
Complaints and Grievances
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Speed
|
|
||||||
~~~~~
|
|
||||||
|
|
||||||
Starting up a phantomjs instance and running a suite turns out to have
|
|
||||||
a rather high overhead, on the order of a second on this machine
|
|
||||||
(2.4GHz, 8GB RAM and an SSD).
|
|
||||||
|
|
||||||
As each ``QUnitSuite`` currently creates its own phantomjs instance,
|
|
||||||
it's probably a good idea to create bigger suites (put many modules &
|
|
||||||
tests in the same QUnit html file, which doesn't preclude splitting
|
|
||||||
them across multiple js files).
|
|
||||||
|
|
||||||
Hacks
|
|
||||||
~~~~~
|
|
||||||
|
|
||||||
QUnitSuite contains a pretty big hack which may or may not cause
|
|
||||||
problem depending on your exact setup: in case of case failure or
|
|
||||||
error, ``unittest.TestResult`` formats the error traceback provided
|
|
||||||
alongside the test object. This goes through Python's
|
|
||||||
traceback-formatting code and there are no hooks there.
|
|
||||||
|
|
||||||
One could expect to use a custom ``TestResult``, but for test suites
|
|
||||||
the ``TestResult`` instance must be provided by the caller, so there
|
|
||||||
is no direct hook onto it.
|
|
||||||
|
|
||||||
This leaves three options:
|
|
||||||
|
|
||||||
* Create a custom ``TestResult`` class and require that it be the one
|
|
||||||
provided to the test suite. This requires altered work flows,
|
|
||||||
customization of the test runner and (as far as I know) isn't
|
|
||||||
available through Python 2.7's autodiscovery. It's the cleanest
|
|
||||||
option but completely fails on practicality.
|
|
||||||
|
|
||||||
* Create a custom ``TestResult`` which directly alters the original
|
|
||||||
result's ``errors`` and ``failures`` attributes as they're part of
|
|
||||||
the testrunner API. This would work but may put custom results in a
|
|
||||||
strange state and break e.g. unittest2's ``@failfast``.
|
|
||||||
|
|
||||||
* Lastly, monkeypatch the undocumented and implementation detail
|
|
||||||
``_exc_info_to_string`` on the provided ``result``. This is the
|
|
||||||
route taken, at least for now.
|
|
||||||
|
|
||||||
.. _QUnit: http://qunitjs.com/
|
|
||||||
|
|
||||||
.. _PhantomJS: http://phantomjs.org/
|
|
||||||
|
|
||||||
.. _Ben Alman: http://benalman.com/
|
|
||||||
|
|
||||||
.. _grunt: http://gruntjs.com/
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* grunt
|
|
||||||
* http://gruntjs.com/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012 "Cowboy" Ben Alman
|
|
||||||
* Licensed under the MIT license.
|
|
||||||
* http://benalman.com/about/license/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*global phantom:true*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
// The page .html file to load.
|
|
||||||
var url = phantom.args[0];
|
|
||||||
// Extra, optionally overridable stuff.
|
|
||||||
var options = JSON.parse(phantom.args[1] || {});
|
|
||||||
|
|
||||||
// Default options.
|
|
||||||
if (!options.timeout) { options.timeout = 5000; }
|
|
||||||
|
|
||||||
// Keep track of the last time a client message was sent.
|
|
||||||
var last = new Date();
|
|
||||||
|
|
||||||
// Messages are sent to the parent by appending them to the tempfile.
|
|
||||||
var sendMessage = function(arg) {
|
|
||||||
var args = Array.isArray(arg) ? arg : [].slice.call(arguments);
|
|
||||||
last = new Date();
|
|
||||||
console.log(JSON.stringify(args));
|
|
||||||
};
|
|
||||||
|
|
||||||
// This allows grunt to abort if the PhantomJS version isn't adequate.
|
|
||||||
sendMessage('private', 'version', phantom.version);
|
|
||||||
|
|
||||||
// Abort if the page doesn't send any messages for a while.
|
|
||||||
setInterval(function() {
|
|
||||||
if (new Date() - last > options.timeout) {
|
|
||||||
sendMessage('fail.timeout');
|
|
||||||
phantom.exit();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// Create a new page.
|
|
||||||
var page = require('webpage').create();
|
|
||||||
|
|
||||||
// The client page must send its messages via alert(jsonstring).
|
|
||||||
page.onAlert = function(args) {
|
|
||||||
sendMessage(JSON.parse(args));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Keep track if the client-side helper script already has been injected.
|
|
||||||
var injected;
|
|
||||||
page.onUrlChanged = function(newUrl) {
|
|
||||||
injected = false;
|
|
||||||
sendMessage('onUrlChanged', newUrl);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Relay console logging messages.
|
|
||||||
page.onConsoleMessage = function(message) {
|
|
||||||
sendMessage('console', message);
|
|
||||||
};
|
|
||||||
|
|
||||||
// For debugging.
|
|
||||||
page.onResourceRequested = function(request) {
|
|
||||||
sendMessage('onResourceRequested', request.url);
|
|
||||||
};
|
|
||||||
|
|
||||||
page.onResourceReceived = function(request) {
|
|
||||||
if (request.stage === 'end') {
|
|
||||||
sendMessage('onResourceReceived', request.url);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Run when the page has finished loading.
|
|
||||||
page.onLoadFinished = function(status) {
|
|
||||||
// The window has loaded.
|
|
||||||
sendMessage('onLoadFinished', status);
|
|
||||||
if (status === 'success') {
|
|
||||||
if (options.inject && !injected) {
|
|
||||||
// Inject client-side helper script, but only if it has not yet been
|
|
||||||
// injected.
|
|
||||||
sendMessage('inject', options.inject);
|
|
||||||
page.injectJs(options.inject);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// File loading failure.
|
|
||||||
sendMessage('fail.load', url);
|
|
||||||
phantom.exit();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Actually load url.
|
|
||||||
page.open(url);
|
|
|
@ -1,22 +0,0 @@
|
||||||
Copyright (c) 2012 "Cowboy" Ben Alman
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
|
||||||
obtaining a copy of this software and associated documentation
|
|
||||||
files (the "Software"), to deal in the Software without
|
|
||||||
restriction, including without limitation the rights to use,
|
|
||||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following
|
|
||||||
conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1 +0,0 @@
|
||||||
{}
|
|
|
@ -1,88 +0,0 @@
|
||||||
/*
|
|
||||||
* grunt
|
|
||||||
* http://gruntjs.com/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012 "Cowboy" Ben Alman
|
|
||||||
* Licensed under the MIT license.
|
|
||||||
* http://benalman.com/about/license/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*global QUnit:true, alert:true*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// Don't re-order tests.
|
|
||||||
QUnit.config.reorder = false;
|
|
||||||
// Run tests serially, not in parallel.
|
|
||||||
QUnit.config.autorun = false;
|
|
||||||
|
|
||||||
// Send messages to the parent PhantomJS process via alert! Good times!!
|
|
||||||
function sendMessage() {
|
|
||||||
var args = [].slice.call(arguments);
|
|
||||||
alert(JSON.stringify(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
// These methods connect QUnit to PhantomJS.
|
|
||||||
QUnit.log(function(obj) {
|
|
||||||
// What is this I don’t even
|
|
||||||
if (obj.message === '[object Object], undefined:undefined') { return; }
|
|
||||||
// Parse some stuff before sending it.
|
|
||||||
var actual = QUnit.jsDump.parse(obj.actual);
|
|
||||||
var expected = QUnit.jsDump.parse(obj.expected);
|
|
||||||
// Send it.
|
|
||||||
sendMessage('qunit.log', obj.result, actual, expected, obj.message, obj.source);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.testStart(function(obj) {
|
|
||||||
sendMessage('qunit.testStart', obj.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.testDone(function(obj) {
|
|
||||||
sendMessage('qunit.testDone', obj.name, obj.failed, obj.passed, obj.total);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.moduleStart(function(obj) {
|
|
||||||
sendMessage('qunit.moduleStart', obj.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.moduleDone(function(obj) {
|
|
||||||
sendMessage('qunit.moduleDone', obj.name, obj.failed, obj.passed, obj.total);
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.begin(function() {
|
|
||||||
sendMessage('qunit.begin');
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.done(function(obj) {
|
|
||||||
sendMessage('qunit.done', obj.failed, obj.passed, obj.total, obj.runtime);
|
|
||||||
});
|
|
||||||
|
|
||||||
// PhantomJS (up to and including 1.7) uses a version of webkit so old
|
|
||||||
// it does not have Function.prototype.bind:
|
|
||||||
// http://code.google.com/p/phantomjs/issues/detail?id=522
|
|
||||||
|
|
||||||
// Use moz polyfill:
|
|
||||||
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind#Compatibility
|
|
||||||
if (!Function.prototype.bind) {
|
|
||||||
Function.prototype.bind = function (oThis) {
|
|
||||||
if (typeof this !== "function") {
|
|
||||||
// closest thing possible to the ECMAScript 5 internal IsCallable function
|
|
||||||
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
|
|
||||||
}
|
|
||||||
|
|
||||||
var aArgs = Array.prototype.slice.call(arguments, 1),
|
|
||||||
fToBind = this,
|
|
||||||
fNOP = function () {},
|
|
||||||
fBound = function () {
|
|
||||||
return fToBind.apply(this instanceof fNOP && oThis
|
|
||||||
? this
|
|
||||||
: oThis,
|
|
||||||
aArgs.concat(Array.prototype.slice.call(arguments)));
|
|
||||||
};
|
|
||||||
|
|
||||||
fNOP.prototype = this.prototype;
|
|
||||||
fBound.prototype = new fNOP();
|
|
||||||
|
|
||||||
return fBound;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,136 +0,0 @@
|
||||||
import json
|
|
||||||
import subprocess
|
|
||||||
import unittest
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
|
|
||||||
ROOT = os.path.join(os.path.dirname(__file__), 'grunt')
|
|
||||||
|
|
||||||
__all__ = ['QUnitSuite']
|
|
||||||
|
|
||||||
def _exc_info_to_string(err, test):
|
|
||||||
return err
|
|
||||||
|
|
||||||
class QUnitTest(unittest.TestCase):
|
|
||||||
def __init__(self, module, name):
|
|
||||||
self.module = module
|
|
||||||
self.name = name
|
|
||||||
self.failed = False
|
|
||||||
def shortDescription(self):
|
|
||||||
return None
|
|
||||||
def __repr__(self):
|
|
||||||
return '<QUnitTest %s:%s>' % (self.module, self.name)
|
|
||||||
def __str__(self):
|
|
||||||
return '%s: %s' % (self.module, self.name)
|
|
||||||
|
|
||||||
class QUnitSuite(unittest.TestSuite):
|
|
||||||
def __init__(self, qunitfile, timeout=5000):
|
|
||||||
super(QUnitSuite, self).__init__()
|
|
||||||
self.testfile = qunitfile
|
|
||||||
self.timeout = timeout
|
|
||||||
self._module = None
|
|
||||||
self._test = None
|
|
||||||
|
|
||||||
def run(self, result):
|
|
||||||
try:
|
|
||||||
subprocess.call(['phantomjs', '-v'],
|
|
||||||
stdout=open(os.devnull, 'w'),
|
|
||||||
stderr=subprocess.STDOUT)
|
|
||||||
except OSError:
|
|
||||||
test = QUnitTest('phantomjs', 'javascript tests')
|
|
||||||
result.startTest(test)
|
|
||||||
result.startTest(test)
|
|
||||||
result.addSkip(test , "phantomjs command not found")
|
|
||||||
result.stopTest(test)
|
|
||||||
return
|
|
||||||
|
|
||||||
result._exc_info_to_string = _exc_info_to_string
|
|
||||||
try:
|
|
||||||
self._run(result)
|
|
||||||
finally:
|
|
||||||
del result._exc_info_to_string
|
|
||||||
|
|
||||||
def _run(self, result):
|
|
||||||
phantom = subprocess.Popen([
|
|
||||||
'phantomjs',
|
|
||||||
'--config=%s' % os.path.join(ROOT, 'phantomjs.json'),
|
|
||||||
os.path.join(ROOT, 'bootstrap.js'), self.testfile,
|
|
||||||
json.dumps({
|
|
||||||
'timeout': self.timeout,
|
|
||||||
'inject': os.path.join(ROOT, 'qunit-phantomjs-bridge.js')
|
|
||||||
})
|
|
||||||
], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
||||||
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
line = phantom.stdout.readline()
|
|
||||||
if line:
|
|
||||||
if self.process(line, result):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
time.sleep(0.1)
|
|
||||||
finally:
|
|
||||||
# If the phantomjs process hasn't quit, kill it
|
|
||||||
if phantom.poll() is None:
|
|
||||||
phantom.terminate()
|
|
||||||
|
|
||||||
def process(self, line, result):
|
|
||||||
try:
|
|
||||||
args = json.loads(line)
|
|
||||||
except ValueError: # phantomjs stderr
|
|
||||||
if 'CoreText' not in line:
|
|
||||||
print line
|
|
||||||
return False
|
|
||||||
event_name = args[0]
|
|
||||||
|
|
||||||
if event_name == 'qunit.done':
|
|
||||||
return True
|
|
||||||
elif event_name == 'fail.load':
|
|
||||||
self.add_error(result, "PhantomJS unable to load %s" % args[1])
|
|
||||||
return True
|
|
||||||
elif event_name == 'fail.timeout':
|
|
||||||
self.add_error(result, "PhantomJS timed out, possibly due to a"
|
|
||||||
" missing QUnit start() call")
|
|
||||||
return True
|
|
||||||
|
|
||||||
elif event_name == 'qunit.moduleStart':
|
|
||||||
self._module = args[1].encode('utf-8') if args[1] else ''
|
|
||||||
elif event_name == 'qunit.moduleStop':
|
|
||||||
self._test = None
|
|
||||||
self._module = None
|
|
||||||
elif event_name == 'qunit.testStart':
|
|
||||||
self._test = QUnitTest(self._module, args[1].encode('utf-8'))
|
|
||||||
result.startTest(self._test)
|
|
||||||
elif event_name == 'qunit.testDone':
|
|
||||||
if not self._test.failed:
|
|
||||||
result.addSuccess(self._test)
|
|
||||||
result.stopTest(self._test)
|
|
||||||
self._test = None
|
|
||||||
elif event_name == 'qunit.log':
|
|
||||||
if args[1]:
|
|
||||||
return False
|
|
||||||
|
|
||||||
self._test.failed = True
|
|
||||||
result.addFailure(
|
|
||||||
self._test, self.failure_to_str(*args[2:]))
|
|
||||||
elif event_name == 'console':
|
|
||||||
print args[1]
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def add_error(self, result, s):
|
|
||||||
test = QUnitTest('phantomjs', 'startup')
|
|
||||||
result.startTest(test)
|
|
||||||
result.addError(test, s)
|
|
||||||
result.stopTest(test)
|
|
||||||
|
|
||||||
def failure_to_str(self, actual, expected, message, source):
|
|
||||||
if message or actual == expected:
|
|
||||||
formatted = str(message or '')
|
|
||||||
else:
|
|
||||||
formatted = "%s != %s" % (actual, expected)
|
|
||||||
|
|
||||||
if source:
|
|
||||||
formatted += '\n\n' + source
|
|
||||||
|
|
||||||
return formatted
|
|
|
@ -1,24 +1,6 @@
|
||||||
import urllib
|
import openerp
|
||||||
import urlparse
|
|
||||||
from openerp import sql_db, tools
|
|
||||||
from qunitsuite.suite import QUnitSuite
|
|
||||||
|
|
||||||
class WebSuite(QUnitSuite):
|
class WebSuite(openerp.tests.HttpCase):
|
||||||
def __init__(self, module):
|
def test_01_js(self):
|
||||||
url = urlparse.urlunsplit([
|
self.phantom_js('/web/tests?mod=web',"","", login='admin')
|
||||||
'http',
|
|
||||||
'localhost:{port}'.format(port=tools.config['xmlrpc_port']),
|
|
||||||
'/web/tests',
|
|
||||||
urllib.urlencode({
|
|
||||||
'mod': module,
|
|
||||||
'source': tools.config['db_name'],
|
|
||||||
'supadmin': tools.config['admin_passwd'],
|
|
||||||
'password': 'admin',
|
|
||||||
}),
|
|
||||||
''
|
|
||||||
])
|
|
||||||
super(WebSuite, self).__init__(url, 50000)
|
|
||||||
|
|
||||||
def load_tests(loader, standard_tests, _):
|
|
||||||
standard_tests.addTest(WebSuite('web'))
|
|
||||||
return standard_tests
|
|
||||||
|
|
|
@ -28,9 +28,7 @@ class LoadTest(common.MockRequestCase):
|
||||||
|
|
||||||
self.MockMenus = model('ir.ui.menu')
|
self.MockMenus = model('ir.ui.menu')
|
||||||
# Mock the absence of custom menu
|
# Mock the absence of custom menu
|
||||||
model('res.users').read.return_value = [{
|
model('res.users').read.return_value = []
|
||||||
'menu_id': False
|
|
||||||
}]
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
del self.MockMenus
|
del self.MockMenus
|
||||||
|
|
|
@ -3,6 +3,101 @@
|
||||||
-->
|
-->
|
||||||
<openerp>
|
<openerp>
|
||||||
<data>
|
<data>
|
||||||
|
<template id="web.assets_common">
|
||||||
|
<script type="text/javascript" src="/web/static/lib/es5-shim/es5-shim.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/underscore/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/underscore.string/lib/underscore.string.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/datejs/globalization/en-US.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/spinjs/spin.js"></script>
|
||||||
|
|
||||||
|
<!-- jQuery stuff -->
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.blockUI/jquery.blockUI.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.hotkeys/jquery.hotkeys.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.placeholder/jquery.placeholder.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.timeago/jquery.timeago.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.form/jquery.form.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/web/static/lib/fontawesome/css/font-awesome.css"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="web.assets_backend">
|
||||||
|
<t t-call="web.assets_common"/>
|
||||||
|
<!-- Datejs -->
|
||||||
|
<script type="text/javascript" src="/web/static/lib/datejs/core.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/datejs/parser.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/datejs/sugarpak.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/datejs/extras.js"></script>
|
||||||
|
|
||||||
|
<!-- jQuery addons -->
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.validate/jquery.validate.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.autosize/jquery.autosize.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.scrollTo/jquery.scrollTo-min.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/web/static/lib/cleditor/jquery.cleditor.css"/>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/cleditor/jquery.cleditor.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/web/static/lib/jquery.textext/jquery.textext.css"/>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.textext/jquery.textext.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/web/static/lib/select2/select2.css"/>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/select2/select2.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- jQuery ui -->
|
||||||
|
<link rel="stylesheet" href="/web/static/lib/jquery.ui.bootstrap/css/custom-theme/jquery-ui-1.9.0.custom.css"/>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.ui/js/jquery-ui-1.9.1.custom.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/web/static/lib/jquery.ui.timepicker/css/jquery-ui-timepicker-addon.css"/>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/web/static/lib/jquery.ui.notify/css/ui.notify.css"/>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/jquery.ui.notify/js/jquery.notify.js"></script>
|
||||||
|
|
||||||
|
<!-- Bootstrap must be loaded after jquery.ui until jquery.ui is removed -->
|
||||||
|
<link rel="stylesheet" href="/web/static/lib/bootstrap/css/bootstrap.css"/>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/bootstrap/js/bootstrap.js"></script>
|
||||||
|
|
||||||
|
<!-- Backbone -->
|
||||||
|
<script type="text/javascript" src="/web/static/lib/backbone/backbone.js"></script>
|
||||||
|
|
||||||
|
<!-- Internals -->
|
||||||
|
<link rel="stylesheet" href="/web/static/src/css/base.css"/>
|
||||||
|
<link rel="stylesheet" href="/web/static/src/css/data_export.css"/>
|
||||||
|
<link rel="stylesheet" href="/base/static/src/css/modules.css"/>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/web/static/lib/qweb/qweb2.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/openerpframework.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/lib/py.js/lib/py.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/boot.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/testing.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/pyeval.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/core.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/formats.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/chrome.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/views.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/data.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/data_export.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/search.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/view_list.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/view_form.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/view_list_editable.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/src/js/view_tree.js"></script>
|
||||||
|
<script type="text/javascript" src="/base/static/src/js/apps.js"></script>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="web.assets_webclient_manifest">
|
||||||
|
<!-- This bundle can be used for module manifest asset declaration backward compatibility -->
|
||||||
|
<t t-foreach="manifest_list('css')" t-as="css_file">
|
||||||
|
<link rel="stylesheet" t-att-href="css_file"/>
|
||||||
|
</t>
|
||||||
|
<t t-foreach="manifest_list('js')" t-as="js_file">
|
||||||
|
<script type="text/javascript" t-att-src="js_file"></script>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template id="web.layout" name="Web layout"><!DOCTYPE html>
|
<template id="web.layout" name="Web layout"><!DOCTYPE html>
|
||||||
<html style="height: 100%">
|
<html style="height: 100%">
|
||||||
|
@ -23,12 +118,7 @@
|
||||||
<template id="web.webclient_bootstrap" name="Webclient Bootstrap">
|
<template id="web.webclient_bootstrap" name="Webclient Bootstrap">
|
||||||
<t t-call="web.layout">
|
<t t-call="web.layout">
|
||||||
<t t-set="head">
|
<t t-set="head">
|
||||||
<t t-foreach="css" t-as="css_file">
|
<t t-call-assets="web.assets_backend"/>
|
||||||
<link rel="stylesheet" t-att-href="css_file"/>
|
|
||||||
</t>
|
|
||||||
<t t-foreach="js" t-as="js_file">
|
|
||||||
<script type="text/javascript" t-att-src="js_file"></script>
|
|
||||||
</t>
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function() {
|
$(function() {
|
||||||
var s = new openerp.init(<t t-raw="modules"/>);
|
var s = new openerp.init(<t t-raw="modules"/>);
|
||||||
|
@ -78,10 +168,10 @@
|
||||||
</script>
|
</script>
|
||||||
<div class="form-group field-db" t-if="databases and len(databases) > 1">
|
<div class="form-group field-db" t-if="databases and len(databases) > 1">
|
||||||
<label for="db" class="control-label">Database</label>
|
<label for="db" class="control-label">Database</label>
|
||||||
<select name="db" id="db" class="form-control" required="required" t-att-autofocus="'autofocus' if current_db not in databases else None" onchange="dbchanged(this.value)">
|
<select name="db" id="db" class="form-control" required="required" t-att-autofocus="'autofocus' if request.db not in databases else None" onchange="dbchanged(this.value)">
|
||||||
<option></option>
|
<option></option>
|
||||||
<t t-foreach="databases" t-as="db">
|
<t t-foreach="databases" t-as="db">
|
||||||
<option t-att-selected="'selected' if db == current_db else None">
|
<option t-att-selected="'selected' if db == request.db else None">
|
||||||
<t t-esc="db"/>
|
<t t-esc="db"/>
|
||||||
</option>
|
</option>
|
||||||
</t>
|
</t>
|
||||||
|
@ -121,5 +211,55 @@
|
||||||
</t>
|
</t>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template id="web.qunit_suite">
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html style="height: 100%">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||||
|
<title>OpenERP Web Tests</title>
|
||||||
|
|
||||||
|
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
|
||||||
|
<link rel="stylesheet" href="/web/static/lib/qunit/qunit.css"/>
|
||||||
|
<script src="/web/static/lib/qunit/qunit.js"></script>
|
||||||
|
|
||||||
|
<t t-call="web.assets_backend"/>
|
||||||
|
|
||||||
|
<script type="text/javascript" id="qunit_config">
|
||||||
|
QUnit.config.testTimeout = 5 * 60 * 1000;
|
||||||
|
QUnit.moduleDone(function(result) {
|
||||||
|
console.log(result.name + " (" + result.passed + "/" + result.total + " passed tests)");
|
||||||
|
});
|
||||||
|
QUnit.done(function(result) {
|
||||||
|
if (result.failed === 0) {
|
||||||
|
console.log('ok');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
openerp.web.qweb.add_template("/web/webclient/qweb");
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/web/static/test/testing.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/framework.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/registry.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/form.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/data.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/list-utils.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/formats.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/rpc-misordered.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/evals.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/search.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/list.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/list-editable.js"></script>
|
||||||
|
<script type="text/javascript" src="/web/static/test/mutex.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body id="oe" class="openerp">
|
||||||
|
<div id="qunit"></div>
|
||||||
|
<div id="qunit-fixture"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</openerp>
|
</openerp>
|
||||||
|
|
|
@ -10,8 +10,4 @@ Openerp Web API.
|
||||||
'depends': ['web'],
|
'depends': ['web'],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'auto_install': False,
|
'auto_install': False,
|
||||||
'js' : [
|
|
||||||
],
|
|
||||||
'css' : [
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,8 @@ OpenERP Web Calendar view.
|
||||||
'author': 'OpenERP SA, Valentino Lab (Kalysto)',
|
'author': 'OpenERP SA, Valentino Lab (Kalysto)',
|
||||||
'version': '2.0',
|
'version': '2.0',
|
||||||
'depends': ['web'],
|
'depends': ['web'],
|
||||||
'data' : [],
|
'data' : [
|
||||||
'js': [
|
'views/web_calendar.xml',
|
||||||
'static/lib/fullcalendar/js/fullcalendar.js',
|
|
||||||
'static/src/js/*.js'
|
|
||||||
],
|
|
||||||
'css': [
|
|
||||||
'static/lib/fullcalendar/css/*.css',
|
|
||||||
'static/src/css/*.css'
|
|
||||||
],
|
],
|
||||||
'qweb': [
|
'qweb': [
|
||||||
'static/src/xml/*.xml',
|
'static/src/xml/*.xml',
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
"X-Poedit-Language: Czech\n"
|
"X-Poedit-Language: Czech\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:41+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:41+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:40+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2014-04-09 06:41+0000\n"
|
"X-Launchpad-Export-Date: 2014-04-26 06:54+0000\n"
|
||||||
"X-Generator: Launchpad (build 16976)\n"
|
"X-Generator: Launchpad (build 16985)\n"
|
||||||
|
|
||||||
#. module: web_calendar
|
#. module: web_calendar
|
||||||
#. openerp-web
|
#. openerp-web
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue