bzr revid: hmo@tinyerp.com-20120809132239-blyhpfxwn2szlqec
This commit is contained in:
Harry (OpenERP)
2012-08-09 18:52:39 +05:30
424 changed files with 26969 additions and 19413 deletions
+7 -3
View File
@@ -3,8 +3,10 @@
"category": "Hidden",
"description":
"""
OpenERP Web core module.
This module provides the core of the OpenERP Web Client.
OpenERP Web core module.
========================
This module provides the core of the OpenERP Web Client.
""",
"depends" : [],
'auto_install': True,
@@ -20,6 +22,7 @@
"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.blockUI/jquery.blockUI.js",
"static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js",
"static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js",
@@ -33,6 +36,7 @@
"static/lib/underscore/underscore.js",
"static/lib/underscore/underscore.string.js",
"static/lib/backbone/backbone.js",
"static/lib/cleditor/jquery.cleditor.js",
"static/lib/py.js/lib/py.js",
"static/src/js/boot.js",
"static/src/js/corelib.js",
@@ -49,7 +53,6 @@
"static/src/js/view_list.js",
"static/src/js/view_list_editable.js",
"static/src/js/view_tree.js",
"static/src/js/view_editor.js"
],
'css' : [
"static/lib/jquery.ui.bootstrap/css/custom-theme/jquery-ui-1.8.16.custom.css",
@@ -60,6 +63,7 @@
"static/src/css/base.css",
"static/src/css/data_export.css",
"static/src/css/data_import.css",
"static/lib/cleditor/jquery.cleditor.css",
],
'qweb' : [
"static/src/xml/*.xml",
+20 -11
View File
@@ -28,6 +28,7 @@ import werkzeug.wsgi
from . import nonliterals
from . import session
from . import openerplib
import urlparse
__all__ = ['Root', 'jsonrequest', 'httprequest', 'Controller',
'WebRequest', 'JsonRequest', 'HttpRequest']
@@ -417,6 +418,23 @@ class ControllerType(type):
class Controller(object):
__metaclass__ = ControllerType
class DisableCacheMiddleware(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
def start_wrapped(status, headers):
referer = environ.get('HTTP_REFERER', '')
parsed = urlparse.urlparse(referer)
debug = parsed.query.count('debug') >= 1
nh = dict(headers)
if 'Last-Modified' in nh: del nh['Last-Modified']
if debug:
if 'Expires' in nh: del nh['Expires']
if 'Etag' in nh: del nh['Etag']
nh['Cache-Control'] = 'no-cache'
start_response(status, nh.items())
return self.app(environ, start_wrapped)
class Root(object):
"""Root WSGI application for the OpenERP Web Client.
@@ -437,7 +455,6 @@ class Root(object):
by the server, will be filtered by this pattern
"""
def __init__(self, options, openerp_addons_namespace=True):
self.root = '/web/webclient/home'
self.config = options
if not hasattr(self.config, 'connector'):
@@ -452,8 +469,8 @@ class Root(object):
static_dirs = self._load_addons(openerp_addons_namespace)
if options.serve_static:
self.dispatch = werkzeug.wsgi.SharedDataMiddleware(
self.dispatch, static_dirs, cache=False)
app = werkzeug.wsgi.SharedDataMiddleware( self.dispatch, static_dirs)
self.dispatch = DisableCacheMiddleware(app)
if options.session_storage:
if not os.path.exists(options.session_storage):
@@ -477,14 +494,6 @@ class Root(object):
request.parameter_storage_class = werkzeug.datastructures.ImmutableDict
request.app = self
if request.path == '/':
params = urllib.urlencode(request.args)
return werkzeug.utils.redirect(self.root + '?' + params, 301)(
environ, start_response)
elif request.path == '/mobile':
return werkzeug.utils.redirect(
'/web_mobile/static/src/web_mobile.html', 301)(environ, start_response)
handler = self.find_handler(*(request.path.split('/')[1:]))
if not handler:
+131 -107
View File
@@ -163,103 +163,133 @@ def sass2scss(src):
return out
return write(sass)
def server_wide_modules(req):
addons = [i for i in req.config.server_wide_modules if i in openerpweb.addons_manifest]
return addons
def manifest_glob(req, addons, key):
if addons is None:
addons = server_wide_modules(req)
else:
addons = addons.split(',')
r = []
for addon in addons:
manifest = openerpweb.addons_manifest.get(addon, None)
if not manifest:
continue
# ensure does not ends with /
addons_path = os.path.join(manifest['addons_path'], '')[:-1]
globlist = manifest.get(key, [])
for pattern in globlist:
for path in glob.glob(os.path.normpath(os.path.join(addons_path, addon, pattern))):
r.append((path, path[len(addons_path):]))
return r
def manifest_list(req, mods, extension):
if not req.debug:
path = '/web/webclient/' + extension
if mods is not None:
path += '?mods=' + mods
return [path]
files = manifest_glob(req, mods, extension)
i_am_diabetic = req.httprequest.environ["QUERY_STRING"].count("no_sugar") >= 1 or \
req.httprequest.environ.get('HTTP_REFERER', '').count("no_sugar") >= 1
if i_am_diabetic:
return [wp for _fp, wp in files]
else:
return ['%s?debug=%s' % (wp, os.path.getmtime(fp)) for fp, wp in files]
def get_last_modified(files):
""" Returns the modification time of the most recently modified
file provided
:param list(str) files: names of files to check
:return: most recent modification time amongst the fileset
:rtype: datetime.datetime
"""
files = list(files)
if files:
return max(datetime.datetime.fromtimestamp(os.path.getmtime(f))
for f in files)
return datetime.datetime(1970, 1, 1)
def make_conditional(req, response, last_modified=None, etag=None):
""" Makes the provided response conditional based upon the request,
and mandates revalidation from clients
Uses Werkzeug's own :meth:`ETagResponseMixin.make_conditional`, after
setting ``last_modified`` and ``etag`` correctly on the response object
:param req: OpenERP request
:type req: web.common.http.WebRequest
:param response: Werkzeug response
:type response: werkzeug.wrappers.Response
:param datetime.datetime last_modified: last modification date of the response content
:param str etag: some sort of checksum of the content (deep etag)
:return: the response object provided
:rtype: werkzeug.wrappers.Response
"""
response.cache_control.must_revalidate = True
response.cache_control.max_age = 0
if last_modified:
response.last_modified = last_modified
if etag:
response.set_etag(etag)
return response.make_conditional(req.httprequest)
class Home(openerpweb.Controller):
_cp_path = '/'
@openerpweb.httprequest
def index(self, req, s_action=None, **kw):
js = "\n ".join('<script type="text/javascript" src="%s"></script>' % i for i in manifest_list(req, None, 'js'))
css = "\n ".join('<link rel="stylesheet" href="%s">' % i for i in manifest_list(req, None, 'css'))
r = html_template % {
'js': js,
'css': css,
'modules': simplejson.dumps(server_wide_modules(req)),
'init': 'var wc = new s.web.WebClient();wc.appendTo($(document.body));'
}
return r
@openerpweb.httprequest
def login(self, req, db, login, key):
return self._login(req, db, login, key)
def _login(self, req, db, login, key, redirect_url='/'):
req.session.authenticate(db, login, key, {})
redirect = werkzeug.utils.redirect(redirect_url, 303)
cookie_val = urllib2.quote(simplejson.dumps(req.session_id))
redirect.set_cookie('instance0|session_id', cookie_val)
return redirect
class WebClient(openerpweb.Controller):
_cp_path = "/web/webclient"
def server_wide_modules(self, req):
addons = [i for i in req.config.server_wide_modules if i in openerpweb.addons_manifest]
return addons
def manifest_glob(self, req, addons, key):
if addons is None:
addons = self.server_wide_modules(req)
else:
addons = addons.split(',')
r = []
for addon in addons:
manifest = openerpweb.addons_manifest.get(addon, None)
if not manifest:
continue
# ensure does not ends with /
addons_path = os.path.join(manifest['addons_path'], '')[:-1]
globlist = manifest.get(key, [])
for pattern in globlist:
for path in glob.glob(os.path.normpath(os.path.join(addons_path, addon, pattern))):
r.append( (path, path[len(addons_path):]))
return r
def manifest_list(self, req, mods, extension):
if not req.debug:
path = '/web/webclient/' + extension
if mods is not None:
path += '?mods=' + mods
return [path]
# old code to force cache reloading
#return ['%s?debug=%s' % (wp, os.path.getmtime(fp)) for fp, wp in self.manifest_glob(req, mods, extension)]
return [el[1] for el in self.manifest_glob(req, mods, extension)]
@openerpweb.jsonrequest
def csslist(self, req, mods=None):
return self.manifest_list(req, mods, 'css')
return manifest_list(req, mods, 'css')
@openerpweb.jsonrequest
def jslist(self, req, mods=None):
return self.manifest_list(req, mods, 'js')
return manifest_list(req, mods, 'js')
@openerpweb.jsonrequest
def qweblist(self, req, mods=None):
return self.manifest_list(req, mods, 'qweb')
def get_last_modified(self, files):
""" Returns the modification time of the most recently modified
file provided
:param list(str) files: names of files to check
:return: most recent modification time amongst the fileset
:rtype: datetime.datetime
"""
files = list(files)
if files:
return max(datetime.datetime.fromtimestamp(os.path.getmtime(f))
for f in files)
return datetime.datetime(1970, 1, 1)
def make_conditional(self, req, response, last_modified=None, etag=None):
""" Makes the provided response conditional based upon the request,
and mandates revalidation from clients
Uses Werkzeug's own :meth:`ETagResponseMixin.make_conditional`, after
setting ``last_modified`` and ``etag`` correctly on the response object
:param req: OpenERP request
:type req: web.common.http.WebRequest
:param response: Werkzeug response
:type response: werkzeug.wrappers.Response
:param datetime.datetime last_modified: last modification date of the response content
:param str etag: some sort of checksum of the content (deep etag)
:return: the response object provided
:rtype: werkzeug.wrappers.Response
"""
response.cache_control.must_revalidate = True
response.cache_control.max_age = 0
if last_modified:
response.last_modified = last_modified
if etag:
response.set_etag(etag)
return response.make_conditional(req.httprequest)
return manifest_list(req, mods, 'qweb')
@openerpweb.httprequest
def css(self, req, mods=None):
files = list(self.manifest_glob(req, mods, 'css'))
last_modified = self.get_last_modified(f[0] for f in files)
files = list(manifest_glob(req, mods, 'css'))
last_modified = get_last_modified(f[0] for f in files)
if req.httprequest.if_modified_since and req.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?://)""", 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"""
@@ -285,57 +315,36 @@ class WebClient(openerpweb.Controller):
content, checksum = concat_files((f[0] for f in files), reader)
return self.make_conditional(
return make_conditional(
req, req.make_response(content, [('Content-Type', 'text/css')]),
last_modified, checksum)
@openerpweb.httprequest
def js(self, req, mods=None):
files = [f[0] for f in self.manifest_glob(req, mods, 'js')]
last_modified = self.get_last_modified(files)
files = [f[0] for f in manifest_glob(req, mods, 'js')]
last_modified = get_last_modified(files)
if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
return werkzeug.wrappers.Response(status=304)
content, checksum = concat_files(files, intersperse=';')
return self.make_conditional(
return make_conditional(
req, req.make_response(content, [('Content-Type', 'application/javascript')]),
last_modified, checksum)
@openerpweb.httprequest
def qweb(self, req, mods=None):
files = [f[0] for f in self.manifest_glob(req, mods, 'qweb')]
last_modified = self.get_last_modified(files)
files = [f[0] for f in manifest_glob(req, mods, 'qweb')]
last_modified = get_last_modified(files)
if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
return werkzeug.wrappers.Response(status=304)
content,checksum = concat_xml(files)
content, checksum = concat_xml(files)
return self.make_conditional(
return make_conditional(
req, req.make_response(content, [('Content-Type', 'text/xml')]),
last_modified, checksum)
@openerpweb.httprequest
def home(self, req, s_action=None, **kw):
js = "\n ".join('<script type="text/javascript" src="%s"></script>'%i for i in self.manifest_list(req, None, 'js'))
css = "\n ".join('<link rel="stylesheet" href="%s">'%i for i in self.manifest_list(req, None, 'css'))
r = html_template % {
'js': js,
'css': css,
'modules': simplejson.dumps(self.server_wide_modules(req)),
'init': 'var wc = new s.web.WebClient();wc.appendTo($(document.body));'
}
return r
@openerpweb.httprequest
def login(self, req, db, login, key):
req.session.authenticate(db, login, key, {})
redirect = werkzeug.utils.redirect('/web/webclient/home', 303)
cookie_val = urllib2.quote(simplejson.dumps(req.session_id))
redirect.set_cookie('instance0|session_id', cookie_val)
return redirect
@openerpweb.jsonrequest
def translations(self, req, mods, lang):
lang_model = req.session.model('res.lang')
@@ -995,6 +1004,16 @@ class DataSet(openerpweb.Controller):
elif isinstance(kwargs[k], common.nonliterals.BaseDomain):
kwargs[k] = req.session.eval_domain(kwargs[k])
# Temporary implements future display_name special field for model#read()
if method == 'read' and kwargs.get('context') and kwargs['context'].get('future_display_name'):
if 'display_name' in args[1]:
names = req.session.model(model).name_get(args[0], **kwargs)
args[1].remove('display_name')
r = getattr(req.session.model(model), method)(*args, **kwargs)
for i in range(len(r)):
r[i]['display_name'] = names[i][1] or "%s#%d" % (model, names[i][0])
return r
return getattr(req.session.model(model), method)(*args, **kwargs)
@openerpweb.jsonrequest
@@ -1358,7 +1377,12 @@ class Binary(openerpweb.Controller):
res = Model.default_get([field], context).get(field)
image_data = base64.b64decode(res)
else:
res = Model.read([int(id)], [last_update, field], context)[0]
try:
id = int(id)
except (ValueError):
# objects might use virtual ids as string
pass
res = Model.read([id], [last_update, field], context)[0]
retag = hashlib.md5(res.get(last_update)).hexdigest()
image_data = base64.b64decode(res.get(field))
except (TypeError, xmlrpclib.Fault):
+331 -314
View File
File diff suppressed because it is too large Load Diff
+786 -646
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+416 -360
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+424 -410
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+330 -310
View File
File diff suppressed because it is too large Load Diff
+316 -300
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+371 -355
View File
File diff suppressed because it is too large Load Diff
+588 -572
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+316 -300
View File
File diff suppressed because it is too large Load Diff
+362 -346
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
+312 -298
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

@@ -0,0 +1,24 @@
.cleditorMain {border:1px solid #999; padding:0 1px 1px; background-color:white}
.cleditorMain iframe {border:none; margin:0; padding:0}
.cleditorMain textarea {border:none; margin:0; padding:0; overflow-y:scroll; font:10pt Arial,Verdana; resize:none; outline:none /* webkit grip focus */}
.cleditorToolbar {background: url('images/toolbar.gif') repeat}
.cleditorGroup {float:left; height:26px}
.cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0; background: url('images/buttons.gif')}
.cleditorDisabled {opacity:0.3; filter:alpha(opacity=30)}
.cleditorDivider {float:left; width:1px; height:23px; margin:1px 0 1px 0; background:#CCC}
.cleditorPopup {border:solid 1px #999; background-color:white; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}
.cleditorList div {padding:2px 4px 2px 4px}
.cleditorList p,
.cleditorList h1,
.cleditorList h2,
.cleditorList h3,
.cleditorList h4,
.cleditorList h5,
.cleditorList h6,
.cleditorList font {padding:0; margin:0; background-color:Transparent}
.cleditorColor {width:150px; padding:1px 0 0 1px}
.cleditorColor div {float:left; width:14px; height:14px; margin:0 1px 1px 0}
.cleditorPrompt {background-color:#F6F7F9; padding:4px; font-size:8.5pt}
.cleditorPrompt input,
.cleditorPrompt textarea {font:8.5pt Arial,Verdana;}
.cleditorMsg {background-color:#FDFCEE; width:150px; padding:4px; font-size:8.5pt}
File diff suppressed because it is too large Load Diff
+31
View File
@@ -0,0 +1,31 @@
/*
CLEditor WYSIWYG HTML Editor v1.3.0
http://premiumsoftware.net/cleditor
requires jQuery v1.4.2 or later
Copyright 2010, Chris Landowski, Premium Software, LLC
Dual licensed under the MIT or GPL Version 2 licenses.
*/
(function(e){function aa(a){var b=this,c=a.target,d=e.data(c,x),h=s[d],f=h.popupName,i=p[f];if(!(b.disabled||e(c).attr(n)==n)){var g={editor:b,button:c,buttonName:d,popup:i,popupName:f,command:h.command,useCSS:b.options.useCSS};if(h.buttonClick&&h.buttonClick(a,g)===false)return false;if(d=="source"){if(t(b)){delete b.range;b.$area.hide();b.$frame.show();c.title=h.title}else{b.$frame.hide();b.$area.show();c.title="Show Rich Text"}setTimeout(function(){u(b)},100)}else if(!t(b))if(f){var j=e(i);if(f==
"url"){if(d=="link"&&M(b)===""){z(b,"A selection is required when inserting a link.",c);return false}j.children(":button").unbind(q).bind(q,function(){var k=j.find(":text"),o=e.trim(k.val());o!==""&&v(b,g.command,o,null,g.button);k.val("http://");r();w(b)})}else f=="pastetext"&&j.children(":button").unbind(q).bind(q,function(){var k=j.find("textarea"),o=k.val().replace(/\n/g,"<br />");o!==""&&v(b,g.command,o,null,g.button);k.val("");r();w(b)});if(c!==e.data(i,A)){N(b,i,c);return false}return}else if(d==
"print")b.$frame[0].contentWindow.print();else if(!v(b,g.command,g.value,g.useCSS,c))return false;w(b)}}function O(a){a=e(a.target).closest("div");a.css(H,a.data(x)?"#FFF":"#FFC")}function P(a){e(a.target).closest("div").css(H,"transparent")}function ba(a){var b=a.data.popup,c=a.target;if(!(b===p.msg||e(b).hasClass(B))){var d=e.data(b,A),h=e.data(d,x),f=s[h],i=f.command,g,j=this.options.useCSS;if(h=="font")g=c.style.fontFamily.replace(/"/g,"");else if(h=="size"){if(c.tagName=="DIV")c=c.children[0];
g=c.innerHTML}else if(h=="style")g="<"+c.tagName+">";else if(h=="color")g=Q(c.style.backgroundColor);else if(h=="highlight"){g=Q(c.style.backgroundColor);if(l)i="backcolor";else j=true}b={editor:this,button:d,buttonName:h,popup:b,popupName:f.popupName,command:i,value:g,useCSS:j};if(!(f.popupClick&&f.popupClick(a,b)===false)){if(b.command&&!v(this,b.command,b.value,b.useCSS,d))return false;r();w(this)}}}function C(a){for(var b=1,c=0,d=0;d<a.length;++d){b=(b+a.charCodeAt(d))%65521;c=(c+b)%65521}return c<<
16|b}function R(a,b,c,d,h){if(p[a])return p[a];var f=e(m).hide().addClass(ca).appendTo("body");if(d)f.html(d);else if(a=="color"){b=b.colors.split(" ");b.length<10&&f.width("auto");e.each(b,function(i,g){e(m).appendTo(f).css(H,"#"+g)});c=da}else if(a=="font")e.each(b.fonts.split(","),function(i,g){e(m).appendTo(f).css("fontFamily",g).html(g)});else if(a=="size")e.each(b.sizes.split(","),function(i,g){e(m).appendTo(f).html("<font size="+g+">"+g+"</font>")});else if(a=="style")e.each(b.styles,function(i,
g){e(m).appendTo(f).html(g[1]+g[0]+g[1].replace("<","</"))});else if(a=="url"){f.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');c=B}else if(a=="pastetext"){f.html("Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>");c=B}if(!c&&!d)c=S;f.addClass(c);l&&f.attr(I,"on").find("div,font,p,h1,h2,h3,h4,h5,h6").attr(I,"on");if(f.hasClass(S)||h===true)f.children().hover(O,P);p[a]=f[0];
return f[0]}function T(a,b){if(b){a.$area.attr(n,n);a.disabled=true}else{a.$area.removeAttr(n);delete a.disabled}try{if(l)a.doc.body.contentEditable=!b;else a.doc.designMode=!b?"on":"off"}catch(c){}u(a)}function v(a,b,c,d,h){D(a);if(!l){if(d===undefined||d===null)d=a.options.useCSS;a.doc.execCommand("styleWithCSS",0,d.toString())}d=true;var f;if(l&&b.toLowerCase()=="inserthtml")y(a).pasteHTML(c);else{try{d=a.doc.execCommand(b,0,c||null)}catch(i){f=i.description;d=false}d||("cutcopypaste".indexOf(b)>
-1?z(a,"For security reasons, your browser does not support the "+b+" command. Try using the keyboard shortcut or context menu instead.",h):z(a,f?f:"Error executing the "+b+" command.",h))}u(a);return d}function w(a){setTimeout(function(){t(a)?a.$area.focus():a.$frame[0].contentWindow.focus();u(a)},0)}function y(a){if(l)return J(a).createRange();return J(a).getRangeAt(0)}function J(a){if(l)return a.doc.selection;return a.$frame[0].contentWindow.getSelection()}function Q(a){var b=/rgba?\((\d+), (\d+), (\d+)/.exec(a),
c=a.split("");if(b)for(a=(b[1]<<16|b[2]<<8|b[3]).toString(16);a.length<6;)a="0"+a;return"#"+(a.length==6?a:c[1]+c[1]+c[2]+c[2]+c[3]+c[3])}function r(){e.each(p,function(a,b){e(b).hide().unbind(q).removeData(A)})}function U(){var a=e("link[href$='jquery.cleditor.css']").attr("href");return a.substr(0,a.length-19)+"images/"}function K(a){var b=a.$main,c=a.options;a.$frame&&a.$frame.remove();var d=a.$frame=e('<iframe frameborder="0" src="javascript:true;">').hide().appendTo(b),h=d[0].contentWindow,f=
a.doc=h.document,i=e(f);f.open();f.write(c.docType+"<html>"+(c.docCSSFile===""?"":'<head><link rel="stylesheet" type="text/css" href="'+c.docCSSFile+'" /></head>')+'<body style="'+c.bodyStyle+'"></body></html>');f.close();l&&i.click(function(){w(a)});E(a);if(l){i.bind("beforedeactivate beforeactivate selectionchange keypress",function(g){if(g.type=="beforedeactivate")a.inactive=true;else if(g.type=="beforeactivate"){!a.inactive&&a.range&&a.range.length>1&&a.range.shift();delete a.inactive}else if(!a.inactive){if(!a.range)a.range=
[];for(a.range.unshift(y(a));a.range.length>2;)a.range.pop()}});d.focus(function(){D(a)})}(e.browser.mozilla?i:e(h)).blur(function(){V(a,true)});i.click(r).bind("keyup mouseup",function(){u(a)});L?a.$area.show():d.show();e(function(){var g=a.$toolbar,j=g.children("div:last"),k=b.width();j=j.offset().top+j.outerHeight()-g.offset().top+1;g.height(j);j=(/%/.test(""+c.height)?b.height():parseInt(c.height))-j;d.width(k).height(j);a.$area.width(k).height(ea?j-2:j);T(a,a.disabled);u(a)})}function u(a){if(!L&&
e.browser.webkit&&!a.focused){a.$frame[0].contentWindow.focus();window.focus();a.focused=true}var b=a.doc;if(l)b=y(a);var c=t(a);e.each(a.$toolbar.find("."+W),function(d,h){var f=e(h),i=e.cleditor.buttons[e.data(h,x)],g=i.command,j=true;if(a.disabled)j=false;else if(i.getEnabled){j=i.getEnabled({editor:a,button:h,buttonName:i.name,popup:p[i.popupName],popupName:i.popupName,command:i.command,useCSS:a.options.useCSS});if(j===undefined)j=true}else if((c||L)&&i.name!="source"||l&&(g=="undo"||g=="redo"))j=
false;else if(g&&g!="print"){if(l&&g=="hilitecolor")g="backcolor";if(!l||g!="inserthtml")try{j=b.queryCommandEnabled(g)}catch(k){j=false}}if(j){f.removeClass(X);f.removeAttr(n)}else{f.addClass(X);f.attr(n,n)}})}function D(a){l&&a.range&&a.range[0].select()}function M(a){D(a);if(l)return y(a).text;return J(a).toString()}function z(a,b,c){var d=R("msg",a.options,fa);d.innerHTML=b;N(a,d,c)}function N(a,b,c){var d,h,f=e(b);if(c){var i=e(c);d=i.offset();h=--d.left;d=d.top+i.height()}else{i=a.$toolbar;
d=i.offset();h=Math.floor((i.width()-f.width())/2)+d.left;d=d.top+i.height()-2}r();f.css({left:h,top:d}).show();if(c){e.data(b,A,c);f.bind(q,{popup:b},e.proxy(ba,a))}setTimeout(function(){f.find(":text,textarea").eq(0).focus().select()},100)}function t(a){return a.$area.is(":visible")}function E(a,b){var c=a.$area.val(),d=a.options,h=d.updateFrame,f=e(a.doc.body);if(h){var i=C(c);if(b&&a.areaChecksum==i)return;a.areaChecksum=i}c=h?h(c):c;c=c.replace(/<(?=\/?script)/ig,"&lt;");if(d.updateTextArea)a.frameChecksum=
C(c);if(c!=f.html()){f.html(c);e(a).triggerHandler(F)}}function V(a,b){var c=e(a.doc.body).html(),d=a.options,h=d.updateTextArea,f=a.$area;if(h){var i=C(c);if(b&&a.frameChecksum==i)return;a.frameChecksum=i}c=h?h(c):c;if(d.updateFrame)a.areaChecksum=C(c);if(c!=f.val()){f.val(c);e(a).triggerHandler(F)}}e.cleditor={defaultOptions:{width:500,height:250,controls:"bold italic underline strikethrough subscript superscript | font size style | color highlight removeformat | bullets numbering | outdent indent | alignleft center alignright justify | undo redo | rule image link unlink | cut copy paste pastetext | print source",
colors:"FFF FCC FC9 FF9 FFC 9F9 9FF CFF CCF FCF CCC F66 F96 FF6 FF3 6F9 3FF 6FF 99F F9F BBB F00 F90 FC6 FF0 3F3 6CC 3CF 66C C6C 999 C00 F60 FC3 FC0 3C0 0CC 36F 63F C3C 666 900 C60 C93 990 090 399 33F 60C 939 333 600 930 963 660 060 366 009 339 636 000 300 630 633 330 030 033 006 309 303",fonts:"Arial,Arial Black,Comic Sans MS,Courier New,Narrow,Garamond,Georgia,Impact,Sans Serif,Serif,Tahoma,Trebuchet MS,Verdana",sizes:"1,2,3,4,5,6,7",styles:[["Paragraph","<p>"],["Header 1","<h1>"],["Header 2","<h2>"],
["Header 3","<h3>"],["Header 4","<h4>"],["Header 5","<h5>"],["Header 6","<h6>"]],useCSS:false,docType:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',docCSSFile:"",bodyStyle:"margin:4px; font:10pt Arial,Verdana; cursor:text"},buttons:{init:"bold,,|italic,,|underline,,|strikethrough,,|subscript,,|superscript,,|font,,fontname,|size,Font Size,fontsize,|style,,formatblock,|color,Font Color,forecolor,|highlight,Text Highlight Color,hilitecolor,color|removeformat,Remove Formatting,|bullets,,insertunorderedlist|numbering,,insertorderedlist|outdent,,|indent,,|alignleft,Align Text Left,justifyleft|center,,justifycenter|alignright,Align Text Right,justifyright|justify,,justifyfull|undo,,|redo,,|rule,Insert Horizontal Rule,inserthorizontalrule|image,Insert Image,insertimage,url|link,Insert Hyperlink,createlink,url|unlink,Remove Hyperlink,|cut,,|copy,,|paste,,|pastetext,Paste as Text,inserthtml,|print,,|source,Show Source"},
imagesPath:function(){return U()}};e.fn.cleditor=function(a){var b=e([]);this.each(function(c,d){if(d.tagName=="TEXTAREA"){var h=e.data(d,Y);h||(h=new cleditor(d,a));b=b.add(h)}});return b};var H="backgroundColor",A="button",x="buttonName",F="change",Y="cleditor",q="click",n="disabled",m="<div>",I="unselectable",W="cleditorButton",X="cleditorDisabled",ca="cleditorPopup",S="cleditorList",da="cleditorColor",B="cleditorPrompt",fa="cleditorMsg",l=e.browser.msie,ea=/msie\s6/i.test(navigator.userAgent),
L=/iphone|ipad|ipod/i.test(navigator.userAgent),p={},Z,s=e.cleditor.buttons;e.each(s.init.split("|"),function(a,b){var c=b.split(","),d=c[0];s[d]={stripIndex:a,name:d,title:c[1]===""?d.charAt(0).toUpperCase()+d.substr(1):c[1],command:c[2]===""?d:c[2],popupName:c[3]===""?d:c[3]}});delete s.init;cleditor=function(a,b){var c=this;c.options=b=e.extend({},e.cleditor.defaultOptions,b);var d=c.$area=e(a).hide().data(Y,c).blur(function(){E(c,true)}),h=c.$main=e(m).addClass("cleditorMain").width(b.width).height(b.height),
f=c.$toolbar=e(m).addClass("cleditorToolbar").appendTo(h),i=e(m).addClass("cleditorGroup").appendTo(f);e.each(b.controls.split(" "),function(g,j){if(j==="")return true;if(j=="|"){e(m).addClass("cleditorDivider").appendTo(i);i=e(m).addClass("cleditorGroup").appendTo(f)}else{var k=s[j],o=e(m).data(x,k.name).addClass(W).attr("title",k.title).bind(q,e.proxy(aa,c)).appendTo(i).hover(O,P),G={};if(k.css)G=k.css;else if(k.image)G.backgroundImage="url("+U()+k.image+")";if(k.stripIndex)G.backgroundPosition=
k.stripIndex*-24;o.css(G);l&&o.attr(I,"on");k.popupName&&R(k.popupName,b,k.popupClass,k.popupContent,k.popupHover)}});h.insertBefore(d).append(d);if(!Z){e(document).click(function(g){g=e(g.target);g.add(g.parents()).is("."+B)||r()});Z=true}/auto|%/.test(""+b.width+b.height)&&e(window).resize(function(){K(c)});K(c)};var $=cleditor.prototype;e.each([["clear",function(a){a.$area.val("");E(a)}],["disable",T],["execCommand",v],["focus",w],["hidePopups",r],["sourceMode",t,true],["refresh",K],["select",
function(a){setTimeout(function(){t(a)?a.$area.select():v(a,"selectall")},0)}],["selectedHTML",function(a){D(a);a=y(a);if(l)return a.htmlText;var b=e("<layer>")[0];b.appendChild(a.cloneContents());return b.innerHTML},true],["selectedText",M,true],["showMessage",z],["updateFrame",E],["updateTextArea",V]],function(a,b){$[b[0]]=function(){for(var c=[this],d=0;d<arguments.length;d++)c.push(arguments[d]);c=b[1].apply(this,c);if(b[2])return c;return this}});$.change=function(a){var b=e(this);return a?b.bind(F,
a):b.trigger(F)}})(jQuery);
@@ -27,7 +27,7 @@
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[0].className = 'tipsy openerp oe_tooltip '; // reset classname in case of dynamic gravity
$tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);
var pos = $.extend({}, this.$element.offset(), {
@@ -63,7 +63,7 @@
}
}
$tip.css(tp).addClass('openerp oe_tooltip tipsy-' + gravity);
$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]));
+306
View File
@@ -0,0 +1,306 @@
//fgnass.github.com/spin.js#v1.2.5
(function(window, document, undefined) {
/**
* Copyright (c) 2011 Felix Gnass [fgnass at neteye dot de]
* Licensed under the MIT license
*/
var prefixes = ['webkit', 'Moz', 'ms', 'O']; /* Vendor prefixes */
var animations = {}; /* Animation rules keyed by their name */
var useCssAnimations;
/**
* Utility function to create elements. If no tag name is given,
* a DIV is created. Optionally properties can be passed.
*/
function createEl(tag, prop) {
var el = document.createElement(tag || 'div');
var n;
for(n in prop) {
el[n] = prop[n];
}
return el;
}
/**
* Appends children and returns the parent.
*/
function ins(parent /* child1, child2, ...*/) {
for (var i=1, n=arguments.length; i<n; i++) {
parent.appendChild(arguments[i]);
}
return parent;
}
/**
* Insert a new stylesheet to hold the @keyframe or VML rules.
*/
var sheet = function() {
var el = createEl('style');
ins(document.getElementsByTagName('head')[0], el);
return el.sheet || el.styleSheet;
}();
/**
* Creates an opacity keyframe animation rule and returns its name.
* Since most mobile Webkits have timing issues with animation-delay,
* we create separate rules for each line/segment.
*/
function addAnimation(alpha, trail, i, lines) {
var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-');
var start = 0.01 + i/lines*100;
var z = Math.max(1-(1-alpha)/trail*(100-start) , alpha);
var prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase();
var pre = prefix && '-'+prefix+'-' || '';
if (!animations[name]) {
sheet.insertRule(
'@' + pre + 'keyframes ' + name + '{' +
'0%{opacity:'+z+'}' +
start + '%{opacity:'+ alpha + '}' +
(start+0.01) + '%{opacity:1}' +
(start+trail)%100 + '%{opacity:'+ alpha + '}' +
'100%{opacity:'+ z + '}' +
'}', 0);
animations[name] = 1;
}
return name;
}
/**
* Tries various vendor prefixes and returns the first supported property.
**/
function vendor(el, prop) {
var s = el.style;
var pp;
var i;
if(s[prop] !== undefined) return prop;
prop = prop.charAt(0).toUpperCase() + prop.slice(1);
for(i=0; i<prefixes.length; i++) {
pp = prefixes[i]+prop;
if(s[pp] !== undefined) return pp;
}
}
/**
* Sets multiple style properties at once.
*/
function css(el, prop) {
for (var n in prop) {
el.style[vendor(el, n)||n] = prop[n];
}
return el;
}
/**
* Fills in default values.
*/
function merge(obj) {
for (var i=1; i < arguments.length; i++) {
var def = arguments[i];
for (var n in def) {
if (obj[n] === undefined) obj[n] = def[n];
}
}
return obj;
}
/**
* Returns the absolute page-offset of the given element.
*/
function pos(el) {
var o = {x:el.offsetLeft, y:el.offsetTop};
while((el = el.offsetParent)) {
o.x+=el.offsetLeft;
o.y+=el.offsetTop;
}
return o;
}
var defaults = {
lines: 12, // The number of lines to draw
length: 7, // The length of each line
width: 5, // The line thickness
radius: 10, // The radius of the inner circle
rotate: 0, // rotation offset
color: '#000', // #rgb or #rrggbb
speed: 1, // Rounds per second
trail: 100, // Afterglow percentage
opacity: 1/4, // Opacity of the lines
fps: 20, // Frames per second when using setTimeout()
zIndex: 2e9, // Use a high z-index by default
className: 'spinner', // CSS class to assign to the element
top: 'auto', // center vertically
left: 'auto' // center horizontally
};
/** The constructor */
var Spinner = function Spinner(o) {
if (!this.spin) return new Spinner(o);
this.opts = merge(o || {}, Spinner.defaults, defaults);
};
Spinner.defaults = {};
merge(Spinner.prototype, {
spin: function(target) {
this.stop();
var self = this;
var o = self.opts;
var el = self.el = css(createEl(0, {className: o.className}), {position: 'relative', zIndex: o.zIndex});
var mid = o.radius+o.length+o.width;
var ep; // element position
var tp; // target position
if (target) {
target.insertBefore(el, target.firstChild||null);
tp = pos(target);
ep = pos(el);
css(el, {
left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : o.left+mid) + 'px',
top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : o.top+mid) + 'px'
});
}
el.setAttribute('aria-role', 'progressbar');
self.lines(el, self.opts);
if (!useCssAnimations) {
// No CSS animation support, use setTimeout() instead
var i = 0;
var fps = o.fps;
var f = fps/o.speed;
var ostep = (1-o.opacity)/(f*o.trail / 100);
var astep = f/o.lines;
!function anim() {
i++;
for (var s=o.lines; s; s--) {
var alpha = Math.max(1-(i+s*astep)%f * ostep, o.opacity);
self.opacity(el, o.lines-s, alpha, o);
}
self.timeout = self.el && setTimeout(anim, ~~(1000/fps));
}();
}
return self;
},
stop: function() {
var el = this.el;
if (el) {
clearTimeout(this.timeout);
if (el.parentNode) el.parentNode.removeChild(el);
this.el = undefined;
}
return this;
},
lines: function(el, o) {
var i = 0;
var seg;
function fill(color, shadow) {
return css(createEl(), {
position: 'absolute',
width: (o.length+o.width) + 'px',
height: o.width + 'px',
background: color,
boxShadow: shadow,
transformOrigin: 'left',
transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)',
borderRadius: (o.width>>1) + 'px'
});
}
for (; i < o.lines; i++) {
seg = css(createEl(), {
position: 'absolute',
top: 1+~(o.width/2) + 'px',
transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
opacity: o.opacity,
animation: useCssAnimations && addAnimation(o.opacity, o.trail, i, o.lines) + ' ' + 1/o.speed + 's linear infinite'
});
if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}));
ins(el, ins(seg, fill(o.color, '0 0 1px rgba(0,0,0,.1)')));
}
return el;
},
opacity: function(el, i, val) {
if (i < el.childNodes.length) el.childNodes[i].style.opacity = val;
}
});
/////////////////////////////////////////////////////////////////////////
// VML rendering for IE
/////////////////////////////////////////////////////////////////////////
/**
* Check and init VML support
*/
!function() {
function vml(tag, attr) {
return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr);
}
var s = css(createEl('group'), {behavior: 'url(#default#VML)'});
if (!vendor(s, 'transform') && s.adj) {
// VML support detected. Insert CSS rule ...
sheet.addRule('.spin-vml', 'behavior:url(#default#VML)');
Spinner.prototype.lines = function(el, o) {
var r = o.length+o.width;
var s = 2*r;
function grp() {
return css(vml('group', {coordsize: s +' '+s, coordorigin: -r +' '+-r}), {width: s, height: s});
}
var margin = -(o.width+o.length)*2+'px';
var g = css(grp(), {position: 'absolute', top: margin, left: margin});
var i;
function seg(i, dx, filter) {
ins(g,
ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
ins(css(vml('roundrect', {arcsize: 1}), {
width: r,
height: o.width,
left: o.radius,
top: -o.width>>1,
filter: filter
}),
vml('fill', {color: o.color, opacity: o.opacity}),
vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
)
)
);
}
if (o.shadow) {
for (i = 1; i <= o.lines; i++) {
seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)');
}
}
for (i = 1; i <= o.lines; i++) seg(i);
return ins(el, g);
};
Spinner.prototype.opacity = function(el, i, val, o) {
var c = el.firstChild;
o = o.shadow && o.lines || 0;
if (c && i+o < c.childNodes.length) {
c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild;
if (c) c.opacity = val;
}
};
}
else {
useCssAnimations = vendor(s, 'animation');
}
}();
window.Spinner = Spinner;
})(window, document);
+458 -144
View File
@@ -20,6 +20,50 @@
font-style: normal;
}
@-moz-keyframes bounce {
0% {
-moz-transform: scale(0);
opacity: 0;
}
50% {
-moz-transform: scale(1.3);
opacity: 0.4;
}
75% {
-moz-transform: scale(0.9);
opacity: 0.7;
}
100% {
-moz-transform: scale(1);
opacity: 1;
}
}
@-webkit-keyframes bounce {
0% {
-webkit-transform: scale(0);
opacity: 0;
}
50% {
-webkit-transform: scale(1.3);
opacity: 0.4;
}
75% {
-webkit-transform: scale(0.9);
opacity: 0.7;
}
100% {
-webkit-transform: scale(1);
opacity: 1;
}
}
.openerp.openerp_webclient_container {
height: 100%;
position: relative;
@@ -34,7 +78,15 @@
background: white;
/* http://www.quirksmode.org/dom/inputfile.html
* http://stackoverflow.com/questions/2855589/replace-input-type-file-by-an-image
*/
*/ */
}
.openerp :-moz-placeholder {
color: #afafb6 !important;
font-style: italic !important;
}
.openerp ::-webkit-input-placeholder {
color: #afafb6 !important;
font-style: italic !important;
}
.openerp a {
text-decoration: none;
@@ -186,6 +238,11 @@
.openerp .ui-menu .ui-menu-item a.ui-state-active {
background: #f0f0fa;
}
.openerp div.ui-widget-overlay {
background: black;
filter: alpha(opacity=30);
opacity: 0.3;
}
.openerp.ui-dialog {
display: none;
padding: 6px;
@@ -234,14 +291,13 @@
.openerp.ui-dialog .ui-dialog-buttonpane {
border-top: 1px solid #e0e0e0;
background: #f5f7f9;
padding: 8px;
margin: 0;
-moz-border-radius: 0 0 2px 2px;
-webkit-border-radius: 0 0 2px 2px;
border-radius: 0 0 2px 2px;
}
.openerp.ui-dialog .ui-dialog-buttonpane button {
margin-left: 8px;
margin: 0;
}
.openerp.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
float: left;
@@ -268,6 +324,45 @@
color: black;
text-decoration: none;
}
.openerp.ui-dialog .oe_about {
background-color: white;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=);
-moz-border-radius: 0 0 2px 2px;
-webkit-border-radius: 0 0 2px 2px;
border-radius: 0 0 2px 2px;
}
.openerp.ui-dialog .oe_about a {
color: #8a89ba;
}
.openerp.ui-dialog .oe_about a:hover {
text-decoration: underline;
}
.openerp.ui-dialog .oe_about .oe_logo {
margin-left: -6px;
}
.openerp.ui-dialog .oe_about .oe_bottom {
position: absolute;
top: 50%;
left: 0;
right: 0;
bottom: 0;
text-shadow: 0 1px 1px #999999;
background-color: #b41616;
background-image: -webkit-gradient(linear, left top, left bottom, from(#b41616), to(#600606));
background-image: -webkit-linear-gradient(top, #b41616, #600606);
background-image: -moz-linear-gradient(top, #b41616, #600606);
background-image: -ms-linear-gradient(top, #b41616, #600606);
background-image: -o-linear-gradient(top, #b41616, #600606);
background-image: linear-gradient(to bottom, #b41616, #600606);
color: #eeeeee;
padding: 0 16px;
-moz-border-radius: 0 0 2px 2px;
-webkit-border-radius: 0 0 2px 2px;
border-radius: 0 0 2px 2px;
}
.openerp.ui-dialog .oe_about .oe_bottom a {
color: #eeeeee;
}
.openerp.ui-dialog.oe_act_window .ui-dialog-content {
padding: 0px;
}
@@ -311,6 +406,7 @@
}
.openerp .oe_fade {
color: #888888;
font-weight: normal;
}
.openerp .oe_bold {
font-weight: bold;
@@ -379,7 +475,8 @@
background: #ed6f6a;
}
.openerp .oe_title {
width: 60%;
width: 50%;
float: left;
}
.openerp .oe_title:after {
content: ".";
@@ -389,17 +486,18 @@
visibility: hidden;
}
.openerp .oe_button_box {
width: 38%;
width: 270px;
text-align: right;
}
.openerp .oe_button_box button {
margin: 4px;
}
.openerp .oe_avatar {
margin: 0 16px 0 0;
margin: 0 6px 15px 0;
}
.openerp .oe_avatar > img {
height: 50px;
height: 90px;
max-width: 100px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
@@ -408,6 +506,17 @@
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
border: none;
}
.openerp .oe_avatar + div {
margin-left: 5px;
}
.openerp .oe_image_small > img {
max-width: 50px;
max-height: 50px;
}
.openerp .oe_image_medium > img {
max-width: 180px;
max-height: 180px;
}
.openerp .oe_button.oe_link {
border: none;
padding: 0;
@@ -497,6 +606,19 @@
.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 {
margin: 8px 0;
padding: 0 16px;
@@ -579,7 +701,7 @@
z-index: 1;
border: 1px solid #afafb6;
background: white;
padding: 6px 0;
padding: 4px 0;
min-width: 140px;
text-align: left;
-moz-border-radius: 3px;
@@ -594,6 +716,7 @@
float: none;
display: block;
position: relative;
padding: 2px 8px;
}
.openerp .oe_dropdown_menu > li:hover {
background-color: #f0f0fa;
@@ -610,7 +733,6 @@
.openerp .oe_dropdown_menu > li > a {
white-space: nowrap;
display: block;
padding: 4px 15px;
color: #4c4c4c;
text-decoration: none;
}
@@ -706,7 +828,7 @@
z-index: 1050;
}
.openerp .oe_login {
background: url("/web/static/src/img/pattern.png") repeat;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=);
text-align: center;
font-size: 14px;
height: 100%;
@@ -940,11 +1062,12 @@
}
.openerp .oe_topbar .oe_dropdown_menu li {
float: none;
padding: 3px 12px;
}
.openerp .oe_topbar .oe_dropdown_menu li a {
color: #eeeeee;
}
.openerp .oe_topbar .oe_dropdown_menu li a:hover {
.openerp .oe_topbar .oe_dropdown_menu li:hover {
background-color: #292929;
background-image: -webkit-gradient(linear, left top, left bottom, from(#292929), to(#191919));
background-image: -webkit-linear-gradient(top, #292929, #191919);
@@ -1224,6 +1347,9 @@
.openerp .oe_view_manager .oe_view_manager_pager {
line-height: 26px;
}
.openerp .oe_view_manager .oe_view_manager_pager .oe_list_pager_single_page .oe_pager_group {
display: none;
}
.openerp .oe_view_manager .oe_pager_value {
float: left;
margin-right: 8px;
@@ -1403,20 +1529,31 @@
filter: alpha(opacity=50);
opacity: 0.5;
}
.openerp .oe_searchview .oe_searchview_search {
font-size: 1px;
letter-spacing: -1px;
color: transparent;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
position: absolute;
left: 3px;
top: 1px;
padding: 0;
border: none;
background: transparent;
}
.openerp .oe_searchview .oe_searchview_search:before {
font: 21px "mnmliconsRegular";
content: "r";
color: #a3a3a3;
}
.openerp .oe_searchview .oe_searchview_facets {
min-height: 22px;
}
.openerp .oe_searchview .oe_searchview_facets:before {
color: #cccccc;
font-family: "mnmliconsRegular";
content: "r";
font-size: 130%;
display: inline;
position: relative;
left: 6px;
top: 2px;
color: #a3a3a3;
padding-right: 4px;
margin-left: 15px;
}
.openerp .oe_searchview .oe_searchview_facets * {
vertical-align: top;
@@ -1432,7 +1569,7 @@
outline: none;
}
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_input {
padding: 0 3px;
padding: 0 0 0 6px;
}
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet {
position: relative;
@@ -1595,14 +1732,14 @@
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section li:hover {
background-color: #f0f0fa;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section form {
.openerp .oe_searchview .oe_searchview_drawer form {
margin-left: 12px;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section form p {
.openerp .oe_searchview .oe_searchview_drawer form p {
margin: 4px 0;
line-height: 18px;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section form button {
.openerp .oe_searchview .oe_searchview_drawer form button {
margin: 0 0 8px 0;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom {
@@ -1696,15 +1833,29 @@
margin: 0 0 0 4px;
padding: 0;
}
.openerp .oe_view_nocontent > img {
float: left;
margin: 1.5em;
}
.openerp .oe_view_nocontent > div {
overflow: hidden;
padding: 35px 0px 0px 0px;
max-width: 700px;
.openerp .oe_view_nocontent {
padding: 15px;
margin-top: 0;
color: #777777;
font-size: 125%;
max-width: 700px;
}
.openerp .oe_view_nocontent .oe_view_nocontent_create {
background: transparent url(/web/static/src/img/view_empty_arrow.png) no-repeat 7px 0;
margin-top: 0;
padding-top: 35px;
min-height: 28px;
color: #4c4c4c;
}
.openerp .oe_view_nocontent > p {
padding-left: 95px;
}
.openerp .oe_view_nocontent .oe_empty_custom_dashboard {
background: transparent url(/web/static/src/img/graph_background.png) no-repeat 0 0;
margin-top: -15px;
padding: 100px 0 0 137px;
min-height: 327px;
margin-left: -15px;
}
.openerp .oe_formview {
background: white;
@@ -1796,6 +1947,16 @@
max-width: 860px;
margin: 0 auto;
}
.openerp .oe_form div.oe_form_configuration div.oe_horizontal_separator {
margin: 25px 0 10px 0;
}
.openerp .oe_form div.oe_form_configuration p {
color: #aaaaaa;
max-width: 650px;
}
.openerp .oe_form div.oe_form_configuration label {
min-width: 150px;
}
.openerp ul.oe_form_steps {
height: 30px;
padding: 0;
@@ -1833,6 +1994,105 @@
font-weight: bold;
color: #b33630;
}
.openerp ul.oe_form_steps_clickable {
height: 30px;
margin: 0;
padding: 0;
text-shadow: 0 1px 1px #cacaca;
box-shadow: 0 0 1px rgba(0, 0, 0, 0.5);
overflow: hidden;
}
.openerp ul.oe_form_steps_clickable li {
border-right: none;
padding: 0 0 0 12px;
position: relative;
float: left;
vertical-align: top;
height: 30px;
color: white;
}
.openerp ul.oe_form_steps_clickable li:after {
content: " ";
width: 0;
height: 0;
border-top: 21px solid transparent;
border-bottom: 21px solid transparent;
border-left: 5px solid #807fb4;
position: absolute;
top: 50%;
margin-top: -21px;
left: 100%;
z-index: 2;
}
.openerp ul.oe_form_steps_clickable li:hover:after {
border-left: 5px solid #807fb4;
}
.openerp ul.oe_form_steps_clickable li:before {
content: " ";
width: 0;
height: 0;
border-top: 21px solid transparent;
border-bottom: 21px solid transparent;
border-left: 5px solid white;
position: absolute;
top: 50%;
margin-top: -21px;
margin-left: 2px;
left: 100%;
z-index: 2;
}
.openerp ul.oe_form_steps_clickable li.oe_form_steps_active {
font-weight: bold;
text-shadow: 0 1px 1px #999999;
box-shadow: inset 0 -1px 1px rgba(0, 0, 0, 0.25), inset 0 1px 1px rgba(255, 255, 255, 0.25);
background-color: #dc5f59;
background: -webkit-linear-gradient(top, #dc5f59, #b33630);
color: white;
}
.openerp ul.oe_form_steps_clickable li.oe_form_steps_inactive {
cursor: pointer;
box-shadow: inset 0 -1px 1px rgba(0, 0, 0, 0.25), inset 0 1px 1px rgba(255, 255, 255, 0.25);
background-color: #adadcf;
background: -webkit-linear-gradient(top, #adadcf, #7c7ba7);
}
.openerp ul.oe_form_steps_clickable li.oe_form_steps_inactive div {
padding: 0 30px 0 0;
}
.openerp ul.oe_form_steps_clickable li.oe_form_steps_inactive:hover {
background: -webkit-linear-gradient(top, #7c7ba7, #adadcf);
}
.openerp ul.oe_form_steps_clickable li div {
padding: 0 30px 0 0;
}
.openerp ul.oe_form_steps_clickable li.oe_form_steps_active:after {
content: " ";
display: block;
width: 0;
height: 0;
border-top: 21px solid transparent;
border-bottom: 21px solid transparent;
border-left: 5px solid #b33630;
position: absolute;
top: 50%;
margin-top: -21px;
left: 100%;
z-index: 2;
}
.openerp ul.oe_form_steps_clickable li.oe_form_steps_active:before {
content: " ";
display: block;
width: 0;
height: 0;
border-top: 21px solid transparent;
border-bottom: 21px solid transparent;
border-left: 5px solid white;
position: absolute;
top: 50%;
margin-top: -21px;
margin-left: 2px;
left: 100%;
z-index: 2;
}
.openerp .oe_form .oe_subtotal_footer {
width: 1% !important;
}
@@ -1849,9 +2109,12 @@
font-weight: bold;
font-size: 18px;
}
.openerp .oe_form .oe_subtotal_footer label:after {
content: ":";
}
.openerp .oe_form .oe_subtotal_footer label.oe_subtotal_footer_separator {
font-weight: bold !important;
padding: 2px 8px 2px 0px !important;
padding: 2px 11px 2px 0px !important;
}
.openerp .oe_form .oe_subtotal_footer label.oe_form_label_help {
font-weight: normal;
@@ -1881,24 +2144,27 @@
.openerp .oe_application .oe_form_sheet .oe_notebook_page {
padding: 0 16px;
}
.openerp .oe_form .oe_form_button {
margin: 2px;
}
.openerp .oe_form td.oe_form_group_cell_label {
border-right: 1px solid #dddddd;
padding: 2px 0px 2px 0px;
padding: 4px 0px 4px 0px;
}
.openerp .oe_form td.oe_form_group_cell_label label {
line-height: 18px;
display: block;
min-width: 110px;
min-width: 120px;
}
.openerp .oe_form td.oe_form_group_cell + .oe_form_group_cell {
padding-left: 6px;
}
.openerp .oe_form .oe_form_group {
width: 100%;
margin: 4px 0 4px 0;
margin: 9px 0 9px 0;
}
.openerp .oe_form .oe_form_group .oe_group_right {
margin-left: 18px;
.openerp .oe_form .oe_form_group .oe_form_group_cell.oe_group_right {
padding-left: 20px;
}
.openerp .oe_form .oe_form_label_help[for], .openerp .oe_form .oe_form_label[for] {
font-weight: bold;
@@ -1920,7 +2186,7 @@
font-weight: bold;
font-size: 20px;
margin: 8px 0px 8px 0px;
color: #aaaabb;
color: #53637e;
}
.openerp .oe_horizontal_separator:empty {
height: 5px;
@@ -1979,7 +2245,7 @@
width: 100%;
display: inline-block;
padding: 2px 2px 2px 0px;
line-height: 18px;
line-height: 1em;
}
.openerp .oe_form .oe_form_field input {
margin: 0px;
@@ -2052,15 +2318,6 @@
.openerp .oe_form .oe_form_field_with_button.oe_no_button > .oe_button {
display: none;
}
.openerp .oe_form .oe_form_field_with_button:not(.oe_no_button) input {
border-right: none;
-webkit-border-top-right-radius: 0px;
-webkit-border-bottom-right-radius: 0px;
-moz-border-radius-topright: 0px;
-moz-border-radius-bottomright: 0px;
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
}
.openerp .oe_form .oe_form_field_with_button:not(.oe_no_button) > .oe_button {
float: right;
-moz-border-radius: 0;
@@ -2077,10 +2334,10 @@
overflow: hidden;
}
.openerp .oe_form_editable .oe_form .oe_form_field_integer {
width: 7em !important;
width: 6em !important;
}
.openerp .oe_form_editable .oe_form .oe_form_field_float {
width: 8em !important;
width: 7em !important;
}
.openerp .oe_form_editable .oe_form .oe_form_field_date {
width: 7.5em !important;
@@ -2139,12 +2396,23 @@
}
.openerp .oe_form_field_many2one span.oe_m2o_drop_down_button {
position: absolute;
top: 1px;
top: 2px;
right: 0px;
}
.openerp .oe_form_field_many2one .oe_m2o_cm_button {
line-height: 14px;
float: right;
padding-left: 2px;
}
.openerp .oe_form .oe_form_field_one2many > .oe_view_manager .oe_list_pager_single_page {
display: none;
}
.openerp .oe_form_field_one2many > .oe_view_manager .oe_list_pager_single_page, .openerp .oe_form_field_many2many > .oe_view_manager .oe_list_pager_single_page {
display: none !important;
}
.openerp .oe_form_field_one2many .oe_form_field_one2many_list_row_add, .openerp .oe_form_field_many2many .oe_form_field_one2many_list_row_add {
font-weight: bold;
}
.openerp .oe_form_field_one2many .oe_list_content > thead, .openerp .oe_form_field_many2many .oe_list_content > thead {
border-bottom: 1px;
}
@@ -2175,15 +2443,91 @@
height: auto;
line-height: 16px;
}
.openerp .oe_form_field_one2many .oe_list_buttons.oe_editing .oe_list_save, .openerp .oe_form_field_many2many .oe_list_buttons.oe_editing .oe_list_save {
visibility: hidden;
}
.openerp .oe_form_editable .oe_list_editable .oe_list_content td.oe_required {
background-color: #d2d2ff;
}
.openerp .oe_form_editable .oe_list_editable .oe_list_content td.oe_readonly {
background-color: #eeeeee;
}
.openerp .oe_list_editable .oe_list_content td.oe_list_field_cell {
padding: 4px 6px 3px 6px;
}
.openerp .oe_list.oe_list_editable td.oe_list_record_delete {
position: absolute;
}
.openerp .oe_list.oe_list_editable.oe_editing .oe_m2o_drop_down_button {
top: 5px;
}
.openerp .oe_list.oe_list_editable.oe_editing .oe_m2o_cm_button {
display: none;
}
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field input {
height: 27px;
}
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field textarea {
border: 1px solid #aaaaff;
border-radius: 0px;
margin: 0px;
-webkit-border-radius: 0px;
}
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field textarea {
height: 60px;
}
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_float input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_view_integer input {
text-align: right;
}
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_datetime > span, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_date > span {
width: 100%;
}
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_datetime input.oe_datepicker_master, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_date input.oe_datepicker_master {
width: 100% !important;
}
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field .oe_form_field_float, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field .oe_form_view_integer, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_datetime, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_date {
min-width: 0 !important;
max-width: none !important;
}
.openerp .oe_form .oe_form_field_many2many > .oe_list .oe_list_pager_single_page {
display: none;
}
.openerp .oe_list_buttons .oe_list_save, .openerp .oe_list_buttons .oe_list_discard {
display: none;
}
.openerp .oe_list_buttons.oe_editing .oe_list_add, .openerp .oe_list_buttons.oe_editing .oe_list_button_import {
display: none;
}
.openerp .oe_list_buttons.oe_editing .oe_list_save {
display: inline-block;
}
.openerp .oe_list_buttons.oe_editing .oe_list_discard {
display: inline;
}
.openerp .oe_list {
position: relative;
}
.openerp .oe_list .oe_form .oe_form_nosheet {
margin: 0;
padding: 0;
border: none;
}
.openerp .oe_list .oe_form .oe_form_field {
width: auto;
position: absolute;
margin: 0 !important;
padding: 0;
}
.openerp .oe_list_content {
width: 100%;
}
.openerp .oe_list_content td:first-child:after, .openerp .oe_list_content th:first-child:after {
border-width: 0;
}
.openerp .oe_list_content td.oe_number {
text-align: right !important;
max-width: 100px;
}
.openerp .oe_list_content > thead {
border-bottom: 2px solid #cacaca;
background: #eeeeee;
@@ -2231,12 +2575,7 @@
}
.openerp .oe_list_content > tbody > tr > td.oe_list_field_cell {
padding: 3px 6px;
}
.openerp .oe_list_content > tbody > tr > td.oe_list_field_cell progress {
width: 100%;
}
.openerp .oe_list_content > tbody > tr > td, .openerp .oe_list_content > tbody > tr > th {
line-height: 18px;
white-space: pre-line;
}
.openerp .oe_list_content > tbody > tr > td > button, .openerp .oe_list_content > tbody > tr > th > button {
border: none;
@@ -2252,10 +2591,6 @@
.openerp .oe_list_content > tbody > tr > td.oe_list_checkbox:first-child:after, .openerp .oe_list_content > tbody > tr th.oe_list_checkbox:first-child:after {
border-width: 0;
}
.openerp .oe_list_content > tbody > tr > td.oe_number {
text-align: right !important;
max-width: 100px;
}
.openerp .oe_list_content > tbody > tr:nth-child(odd) {
background-color: #f0f0fa;
background-color: #f0f0fa;
@@ -2272,15 +2607,6 @@
background: #eeeeee;
font-weight: bold;
}
.openerp .oe_list_content > tbody tr:hover td, .openerp .oe_list_content tbody tr:hover th {
background-color: #eeeeee;
background-image: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#dedede));
background-image: -webkit-linear-gradient(top, #eeeeee, #dedede);
background-image: -moz-linear-gradient(top, #eeeeee, #dedede);
background-image: -ms-linear-gradient(top, #eeeeee, #dedede);
background-image: -o-linear-gradient(top, #eeeeee, #dedede);
background-image: linear-gradient(to bottom, #eeeeee, #dedede);
}
.openerp .oe_list_content .numeric {
text-align: right;
width: 82px;
@@ -2288,74 +2614,25 @@
.openerp .oe_list_content .numeric input {
text-align: right;
}
.openerp .oe_list_content .oe_list_edit_row_save:before {
content: "S";
.openerp .oe_list_content th.oe_list_header_handle {
font-size: 1px;
overflow: hidden;
text-indent: -9001px;
}
.openerp .oe_trad_field.touched {
border: 1px solid green !important;
.openerp .oe_list_content td.oe_list_field_handle {
width: 1em;
cursor: ns-resize;
}
.openerp .oe_view_editor {
width: 100%;
border-collapse: collapse;
margin-left: -12px;
width: 100%;
background-color: white;
border-spacing: 0;
.openerp .oe_list_content td.oe_list_field_handle .oe_list_handle {
font-size: 1px;
letter-spacing: -1px;
color: transparent;
}
.openerp .oe_view_editor td {
text-align: center;
white-space: nowrap;
border: 1px solid #d8d8d8;
cursor: pointer;
font-size: 90%;
.openerp .oe_list_content td.oe_list_field_handle .oe_list_handle:before {
font: 21px "mnmliconsRegular";
content: "ö";
color: #404040;
}
.openerp .oe_view_editor_field td {
border: 0px !important;
}
.openerp .oe_view_editor tr:hover {
background-color: #ecebf2;
}
.openerp .oe_layout_debugging .oe_form_group {
outline: 2px dashed green;
}
.openerp .oe_layout_debugging .oe_form_group_cell {
outline: 1px solid blue;
}
.openerp .oe_layout_debugging .oe_form_group:hover, .openerp .oe_layout_debugging .oe_form_group_cell:hover {
outline-color: red;
}
.openerp .oe_layout_debugging .oe_form_group_row_incomplete > td:last-child:after {
content: "[Incomplete Row]";
background: red;
padding: 2px;
font-weight: bold;
color: white;
float: right;
}
.openerp .oe_layout_debugging .oe_form_group_row_incomplete.oe_form_group_row_newline > td:last-child:after {
content: "[newline]";
}
.openerp .oe_debug_view {
float: left;
}
.openerp .oe_debug_view_log {
font-size: 95%;
}
.openerp .oe_debug_view_log label {
display: block;
width: 49%;
text-align: right;
float: left;
font-weight: bold;
color: #000099;
}
.openerp .oe_debug_view_log span {
display: block;
width: 49%;
float: right;
color: #333333;
}
.openerp .tree_header {
background-color: #f0f0f0;
border-bottom: 1px solid #cacaca;
@@ -2408,6 +2685,49 @@
.openerp .oe-treeview-table .treeview-tr.oe-treeview-first span, .openerp .oe-treeview-table .treeview-td.oe-treeview-first span {
margin-left: 16px;
}
.openerp .oe_trad_field.touched {
border: 1px solid green !important;
}
.openerp .oe_layout_debugging .oe_form_group {
outline: 2px dashed green;
}
.openerp .oe_layout_debugging .oe_form_group_cell {
outline: 1px solid blue;
}
.openerp .oe_layout_debugging .oe_form_group:hover, .openerp .oe_layout_debugging .oe_form_group_cell:hover {
outline-color: red;
}
.openerp .oe_layout_debugging .oe_form_group_row_incomplete > td:last-child:after {
content: "[Incomplete Row]";
background: red;
padding: 2px;
font-weight: bold;
color: white;
float: right;
}
.openerp .oe_layout_debugging .oe_form_group_row_incomplete.oe_form_group_row_newline > td:last-child:after {
content: "[newline]";
}
.openerp .oe_debug_view {
float: left;
}
.openerp .oe_debug_view_log {
font-size: 95%;
}
.openerp .oe_debug_view_log label {
display: block;
width: 49%;
text-align: right;
float: left;
font-weight: bold;
color: #000099;
}
.openerp .oe_debug_view_log span {
display: block;
width: 49%;
float: right;
color: #333333;
}
.kitten-mode-activated {
background-image: url(http://placekitten.com/g/1365/769);
@@ -2417,9 +2737,3 @@
.kitten-mode-activated > * {
opacity: 0.7;
}
div.ui-widget-overlay {
background: black;
filter: alpha(opacity=30);
opacity: 0.3;
}
+389 -142
View File
@@ -92,12 +92,40 @@ $sheet-max-width: 860px
letter-spacing: -1px
color: transparent
&:before
font-family: "mnmliconsRegular"
font: 21px "mnmliconsRegular"
content: $icon-name
font-size: 20px
color: $color
// }}}
// CSS animation bounces {{{
@-moz-keyframes bounce
0%
-moz-transform: scale(0)
opacity: 0
50%
-moz-transform: scale(1.3)
opacity: 0.4
75%
-moz-transform: scale(0.9)
opacity: 0.7
100%
-moz-transform: scale(1)
opacity: 1
@-webkit-keyframes bounce
0%
-webkit-transform: scale(0)
opacity: 0
50%
-webkit-transform: scale(1.3)
opacity: 0.4
75%
-webkit-transform: scale(0.9)
opacity: 0.7
100%
-webkit-transform: scale(1)
opacity: 1
// }}}
.openerp.openerp_webclient_container
height: 100%
@@ -112,6 +140,14 @@ $sheet-max-width: 860px
font-size: 13px
background: white
// }}}
//Placeholder style{{{
\:-moz-placeholder
color: $facets-border !important
font-style: italic !important
\::-webkit-input-placeholder
color: $facets-border !important
font-style: italic !important
//}}}
// Tag reset {{{
a
text-decoration: none
@@ -122,7 +158,7 @@ $sheet-max-width: 860px
font-weight: bold
background-color: #f0f0f0
th
border-right: 1px dotted #afafb6
border-right: 1px dotted $facets-border
&:last-child
border-right: none
th, td
@@ -201,7 +237,9 @@ $sheet-max-width: 860px
width: auto
a.ui-state-active
background: #f0f0fa
div.ui-widget-overlay
background: black
@include opacity(0.3)
// Modal box
&.ui-dialog
display: none
@@ -232,11 +270,10 @@ $sheet-max-width: 860px
.ui-dialog-buttonpane
border-top: 1px solid #e0e0e0
background: #f5f7f9
padding: 8px
margin: 0
@include radius(0 0 2px 2px)
button
margin-left: 8px
margin: 0
.ui-dialog-buttonset
float: left
.ui-dialog-titlebar-close
@@ -257,6 +294,29 @@ $sheet-max-width: 860px
&:hover
color: black
text-decoration: none
.oe_about
background-color: white
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=)
@include radius(0 0 2px 2px)
a
color: #8A89BA
&:hover
text-decoration: underline
.oe_logo
margin-left: -6px
.oe_bottom
position: absolute
top: 50%
left: 0
right: 0
bottom: 0
text-shadow: 0 1px 1px #999999
@include vertical-gradient(#b41616, #600606)
color: #eee
padding: 0 16px
@include radius(0 0 2px 2px)
a
color: #eee
&.ui-dialog.oe_act_window
.ui-dialog-content
@@ -296,6 +356,7 @@ $sheet-max-width: 860px
cursor: wait
.oe_fade
color: #888
font-weight: normal
.oe_bold
font-weight: bold
.oe_inline
@@ -324,7 +385,8 @@ $sheet-max-width: 860px
&:hover
background: #ED6F6A
.oe_title
width: 60%
width: 50%
float: left
.oe_title:after
content: "."
display: block
@@ -332,17 +394,26 @@ $sheet-max-width: 860px
clear: both
visibility: hidden
.oe_button_box
width: 38%
width: 270px
text-align: right
button
margin: 4px
.oe_avatar
margin: 0 16px 0 0
margin: 0 6px 15px 0
> img
height: 50px
height: 90px
max-width: 100px
@include radius(3px)
@include box-shadow(0 1px 3px rgba(0, 0, 0, 0.3))
border: none
.oe_avatar + div
margin-left: 5px
.oe_image_small > img
max-width: 50px
max-height: 50px
.oe_image_medium > img
max-width: 180px
max-height: 180px
.oe_button.oe_link
@include reset()
img
@@ -401,6 +472,16 @@ $sheet-max-width: 860px
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 {{{
.oe_notebook
@@ -464,9 +545,9 @@ $sheet-max-width: 860px
top: 26px
left: 0
z-index: 1
border: 1px solid #afafb6
border: 1px solid $facets-border
background: white
padding: 6px 0
padding: 4px 0
min-width: 140px
text-align: left
@include radius(3px)
@@ -479,10 +560,10 @@ $sheet-max-width: 860px
float: none
display: block
position: relative
padding: 2px 8px
> a
white-space: nowrap
display: block
padding: 4px 15px
color: #4c4c4c
text-decoration: none
&:hover
@@ -563,7 +644,7 @@ $sheet-max-width: 860px
// }}}
// Login {{{
.oe_login
background: url("/web/static/src/img/pattern.png") repeat
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=)
text-align: center
font-size: 14px
height: 100%
@@ -731,11 +812,12 @@ $sheet-max-width: 860px
@include background-clip()
li
float: none
padding: 3px 12px
a
color: #eee
&:hover
@include vertical-gradient(#292929, #191919)
@include box-shadow(none)
&:hover
@include vertical-gradient(#292929, #191919)
@include box-shadow(none)
// }}}
// Webclient.leftbar {{{
@@ -743,7 +825,7 @@ $sheet-max-width: 860px
display: none
width: 220px
background: #f0eeee
border-right: 1px solid #afafb6
border-right: 1px solid $facets-border
text-shadow: 0 1px 1px white
padding-bottom: 16px
a.oe_logo
@@ -955,6 +1037,8 @@ $sheet-max-width: 860px
// ViewManager.pager {{{
.oe_view_manager_pager
line-height: 26px
.oe_list_pager_single_page .oe_pager_group
display: none
.oe_pager_value
float: left
margin-right: 8px
@@ -1098,19 +1182,20 @@ $sheet-max-width: 860px
border-right: 5px solid transparent
@include opacity()
.oe_searchview_search
@include text-to-icon("r", #a3a3a3)
@include box-shadow(none)
@include radius(0)
position: absolute
left: 3px
top: 1px
padding: 0
border: none
background: transparent
.oe_searchview_facets
min-height: 22px
&:before
color: #ccc
font-family: "mnmliconsRegular"
content: "r"
font-size: 130%
display: inline
position: relative
left: 6px
top: 2px
color: #a3a3a3
padding-right: 4px
margin-left: 15px
*
vertical-align: top
display: inline-block
@@ -1122,7 +1207,7 @@ $sheet-max-width: 860px
&:focus
outline: none
.oe_searchview_input
padding: 0 3px
padding: 0 0 0 6px
.oe_searchview_facet
position: relative
cursor: pointer
@@ -1181,7 +1266,7 @@ $sheet-max-width: 860px
background-color: white
min-width: 100%
display: none
border: 1px solid #afafb6
border: 1px solid $facets-border
text-align: left
@include radius(4px)
@include box-shadow(0 1px 4px rgba(0,0,0,0.3))
@@ -1244,13 +1329,13 @@ $sheet-max-width: 860px
// after oe_selected so background color is not overridden
&:hover
background-color: $hover-background
form
margin-left: 12px
p
margin: 4px 0
line-height: 18px
button
margin: 0 0 8px 0
form
margin-left: 12px
p
margin: 4px 0
line-height: 18px
button
margin: 0 0 8px 0
.oe_searchview_custom
padding: 0 8px 8px 8px
form
@@ -1336,15 +1421,26 @@ $sheet-max-width: 860px
// }}}
// Views Common {{{
.oe_view_nocontent
> img
float: left
margin: 1.5em
> div
// don't encroach on my arrow
overflow: hidden
padding: 35px 0px 0px 0px
max-width: 700px
font-size: 125%
padding: 15px
margin-top: 0
color: #777777
font-size: 125%
max-width: 700px
.oe_view_nocontent_create
background: transparent url(/web/static/src/img/view_empty_arrow.png) no-repeat 7px 0
margin-top: 0
padding-top: 35px
min-height: 28px
color: #4c4c4c
> p
padding-left: 95px
.oe_empty_custom_dashboard
background: transparent url(/web/static/src/img/graph_background.png) no-repeat 0 0
margin-top: -15px
padding: 100px 0 0 137px
min-height: 327px
margin-left: -15px
// }}}
// FormView.base and dynamic tags {{{
.oe_formview
@@ -1398,6 +1494,14 @@ $sheet-max-width: 860px
min-width: 650px
max-width: $sheet-max-width
margin: 0 auto
div.oe_form_configuration
div.oe_horizontal_separator
margin: 25px 0 10px 0
p
color: #aaa
max-width: 650px
label
min-width: 150px
ul.oe_form_steps
height: 30px
padding: 0
@@ -1427,6 +1531,93 @@ $sheet-max-width: 860px
.oe_form_steps_active
font-weight: bold
color: #b33630
ul.oe_form_steps_clickable
height: 30px
margin: 0
padding: 0
text-shadow: 0 1px 1px #cacaca
box-shadow: 0 0 1px rgba(0,0,0,0.5)
overflow: hidden
li
border-right: none
padding: 0 0 0 12px
position: relative
float: left
vertical-align: top
height: 30px
color: white
&:after
content: " "
width: 0
height: 0
border-top: 21px solid transparent
border-bottom: 21px solid transparent
border-left: 5px solid #807fb4
position: absolute
top: 50%
margin-top: -21px
left: 100%
z-index: 2
&:hover:after
border-left: 5px solid #807fb4
&:before
content: " "
width: 0
height: 0
border-top: 21px solid transparent
border-bottom: 21px solid transparent
border-left: 5px solid white
position: absolute
top: 50%
margin-top: -21px
margin-left: 2px
left: 100%
z-index: 2
&.oe_form_steps_active
font-weight: bold
text-shadow: 0 1px 1px #999999
box-shadow: inset 0 -1px 1px rgba(0,0,0,0.25), inset 0 1px 1px rgba(255,255,255,0.25)
background-color: #dc5f59
background: -webkit-linear-gradient(top, #dc5f59, #b33630)
color: white
&.oe_form_steps_inactive
cursor: pointer
box-shadow: inset 0 -1px 1px rgba(0,0,0,0.25), inset 0 1px 1px rgba(255,255,255,0.25)
background-color: #adadcf
background: -webkit-linear-gradient(top, #adadcf, #7c7ba7)
div
padding: 0 30px 0 0
&.oe_form_steps_inactive:hover
background: -webkit-linear-gradient(top, #7c7ba7, #adadcf)
div
padding: 0 30px 0 0
&.oe_form_steps_active:after
content: " "
display: block
width: 0
height: 0
border-top: 21px solid transparent
border-bottom: 21px solid transparent
border-left: 5px solid #b33630
position: absolute
top: 50%
margin-top: -21px
left: 100%
z-index: 2
&.oe_form_steps_active:before
content: " "
display: block
width: 0
height: 0
border-top: 21px solid transparent
border-bottom: 21px solid transparent
border-left: 5px solid white
position: absolute
top: 50%
margin-top: -21px
margin-left: 2px
left: 100%
z-index: 2
.oe_form .oe_subtotal_footer
width: 1% !important
td.oe_form_group_cell
@@ -1439,9 +1630,11 @@ $sheet-max-width: 860px
border-top: 1px solid #cacaca
font-weight: bold
font-size: 18px
label:after
content: ":"
label.oe_subtotal_footer_separator
font-weight: bold !important
padding: 2px 8px 2px 0px !important
padding: 2px 11px 2px 0px !important
label.oe_form_label_help
font-weight: normal
// no sheet in popups
@@ -1458,7 +1651,7 @@ $sheet-max-width: 860px
background: white
min-height: 330px
padding: 16px
border: 1px solid #afafb6
border: 1px solid $facets-border
@include box-shadow(0 0 10px rgba(0,0,0,0.3))
.ui-tabs
margin: 0 -16px
@@ -1467,20 +1660,22 @@ $sheet-max-width: 860px
// }}}
// FormView.group {{{
.oe_form
.oe_form_button
margin: 2px
td.oe_form_group_cell_label
border-right: 1px solid #ddd
padding: 2px 0px 2px 0px
padding: 4px 0px 4px 0px
label
line-height: 18px
display: block
min-width: 110px
min-width: 120px
td.oe_form_group_cell + .oe_form_group_cell
padding-left: 6px
.oe_form_group
width: 100%
margin: 4px 0 4px 0
.oe_group_right
margin-left: 18px
margin: 9px 0 9px 0
.oe_form_group_cell.oe_group_right
padding-left: 20px
// }}}
// FormView.label {{{
.oe_form
@@ -1503,7 +1698,7 @@ $sheet-max-width: 860px
font-weight: bold
font-size: 20px
margin: 8px 0px 8px 0px
color: #aab
color: #53637e
.oe_horizontal_separator:empty
height: 5px
.oe_vertical_separator
@@ -1550,7 +1745,7 @@ $sheet-max-width: 860px
width: 100%
display: inline-block
padding: 2px 2px 2px 0px
line-height: 18px
line-height: 1em
input
margin: 0px
input[type="text"], input[type="password"], input[type="file"], select
@@ -1603,14 +1798,6 @@ $sheet-max-width: 860px
.oe_form_field_with_button.oe_no_button > .oe_button
display: none
.oe_form_field_with_button:not(.oe_no_button)
input
border-right: none
-webkit-border-top-right-radius: 0px
-webkit-border-bottom-right-radius: 0px
-moz-border-radius-topright: 0px
-moz-border-radius-bottomright: 0px
border-top-right-radius: 0px
border-bottom-right-radius: 0px
> .oe_button
float: right
@include radius(0)
@@ -1625,9 +1812,9 @@ $sheet-max-width: 860px
.oe_form_editable
.oe_form
.oe_form_field_integer
width: 7em !important
width: 6em !important
.oe_form_field_float
width: 8em !important
width: 7em !important
.oe_form_field_date
width: 7.5em !important
.oe_form_field_datetime
@@ -1684,8 +1871,12 @@ $sheet-max-width: 860px
position: relative
span.oe_m2o_drop_down_button
position: absolute
top: 1px
top: 2px
right: 0px
.oe_m2o_cm_button
line-height: 14px
float: right
padding-left: 2px
// }}}
// FormView.one2many {{{
.oe_form .oe_form_field_one2many > .oe_view_manager
@@ -1693,6 +1884,11 @@ $sheet-max-width: 860px
display: none
.oe_form_field_one2many,.oe_form_field_many2many
// TODO: oe_form_field_one2many_list?
> .oe_view_manager
.oe_list_pager_single_page
display: none !important
.oe_form_field_one2many_list_row_add
font-weight: bold
.oe_list_content
> thead
border-bottom: 1px
@@ -1719,6 +1915,49 @@ $sheet-max-width: 860px
li
height: auto
line-height: 16px
.oe_list_buttons.oe_editing .oe_list_save
// keep "save row" button hidden in o2m
visibility: hidden
.oe_form_editable
.oe_list_editable
.oe_list_content
td.oe_required
background-color: #d2d2ff
td.oe_readonly
background-color: #eee
.oe_list_editable
.oe_list_content
td.oe_list_field_cell
padding: 4px 6px 3px 6px
.oe_list.oe_list_editable
td.oe_list_record_delete
position: absolute
.oe_list.oe_list_editable.oe_editing
.oe_m2o_drop_down_button
top: 5px
.oe_m2o_cm_button
display: none
.oe_form_field
input
height: 27px
input, textarea
border: 1px solid #aaf
border-radius: 0px
margin: 0px
-webkit-border-radius: 0px
textarea
height: 60px
&.oe_form_field_float,&.oe_form_view_integer
input
text-align: right
&.oe_form_field_datetime,&.oe_form_field_date
> span
width: 100%
input.oe_datepicker_master
width: 100% !important
.oe_form_field_float,.oe_form_view_integer,&.oe_form_field_datetime,&.oe_form_field_date
min-width: 0 !important
max-width: none !important
// }}}
// FormView.many2many {{{
.oe_form .oe_form_field_many2many > .oe_list
@@ -1726,11 +1965,38 @@ $sheet-max-width: 860px
display: none
// }}}
// ListView {{{
.oe_list_buttons
.oe_list_save, .oe_list_discard
display: none
&.oe_editing
.oe_list_add, .oe_list_button_import
display: none
.oe_list_save
display: inline-block
.oe_list_discard
display: inline
.oe_list
position: relative
.oe_form
.oe_form_nosheet
margin: 0 // FIXME: either class or border should not be by default
padding: 0
border: none
.oe_form_field
width: auto
position: absolute
margin: 0 !important // dammit
padding: 0
.oe_list_content
width: 100%
td:first-child, th:first-child
&:after
border-width: 0
td.oe_number
text-align: right !important
max-width: 100px
> thead
border-bottom: 2px solid #cacaca
background: #eee
@@ -1766,10 +2032,8 @@ $sheet-max-width: 860px
border-top: 1px solid #ddd
> td.oe_list_field_cell
padding: 3px 6px
progress
width: 100%
white-space: pre-line
> td, > th
line-height: 18px
> button
border: none
background: transparent
@@ -1779,9 +2043,6 @@ $sheet-max-width: 860px
width: 17px
&:after
border-width: 0
> td.oe_number
text-align: right !important
max-width: 100px
> tr:nth-child(odd)
background-color: #f0f0fa
@include vertical-gradient(#f0f0fa, #eeeef6)
@@ -1791,40 +2052,70 @@ $sheet-max-width: 860px
background: #eee
font-weight: bold
> tbody tr:hover td, tbody tr:hover th
@include vertical-gradient(#eee, #dedede)
.numeric
text-align: right
width: 82px
input
text-align: right
.oe_list_edit_row_save:before
content: "S"
th.oe_list_header_handle
font-size: 1px
overflow: hidden
text-indent: -9001px
td.oe_list_field_handle
width: 1em
cursor: ns-resize
.oe_list_handle
@include text-to-icon("ö")
// }}}
// Tree view {{{
.tree_header
background-color: #f0f0f0
border-bottom: 1px solid #cacaca
color: #4c4c4c
padding: 5px
height: 25px
button
float: right
height: 27px
margin-right: 5px
.oe-treeview-table
width: 100%
background-color: white
border-spacing: 0
th
padding: 10px
color: #4c4c4c
font-weight: bold
background-color: #f0f0f0
border-bottom: 2px solid #cacaca
.treeview-tr, .treeview-td
cursor: pointer
border-right: 1px dotted $facets-border
vertical-align: top
text-align: left
border-bottom: 1px solid #cfcccc
tr:hover
background-color: #e0e0f8
.oe-number
text-align: right !important
span
font-size: 90%
font-weight: normal
white-space: nowrap
display: block
.treeview-tr.oe-treeview-first
background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat
.oe_open .treeview-tr.oe-treeview-first
background-image: url(/web/static/src/img/collapse.gif)
.treeview-tr.oe-treeview-first span, .treeview-td.oe-treeview-first span
margin-left: 16px
// }}}
// Translation {{{
.oe_trad_field.touched
border: 1px solid green !important
// }}}
// View Editor {{{
.oe_view_editor
width: 100%
border-collapse: collapse
margin-left: -12px
width: 100%
background-color: white
border-spacing: 0
td
text-align: center
white-space: nowrap
border: 1px solid #D8D8D8
cursor: pointer
font-size: 90%
.oe_view_editor_field td
border: 0px !important
.oe_view_editor tr:hover
background-color: #ecebf2
// }}}
// Debugging stuff {{{
.oe_layout_debugging
.oe_form_group
@@ -1859,49 +2150,6 @@ $sheet-max-width: 860px
float: right
color: #333
// }}}
//Tree view
.openerp
.tree_header
background-color: #f0f0f0
border-bottom: 1px solid #cacaca
color: #4c4c4c
padding: 5px
height: 25px
button
float: right
height: 27px
margin-right: 5px
.oe-treeview-table
width: 100%
background-color: white
border-spacing: 0
th
padding: 10px
color: #4c4c4c
font-weight: bold
background-color: #f0f0f0
border-bottom: 2px solid #cacaca
.treeview-tr, .treeview-td
cursor: pointer
border-right: 1px dotted #afafb6
vertical-align: top
text-align: left
border-bottom: 1px solid #cfcccc
tr:hover
background-color: #e0e0f8
.oe-number
text-align: right !important
span
font-size: 90%
font-weight: normal
white-space: nowrap
display: block
.treeview-tr.oe-treeview-first
background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat
.oe_open .treeview-tr.oe-treeview-first
background-image: url(/web/static/src/img/collapse.gif)
.treeview-tr.oe-treeview-first span, .treeview-td.oe-treeview-first span
margin-left: 16px
// Kitten Mode {{{
.kitten-mode-activated
background-image: url(http://placekitten.com/g/1365/769)
@@ -1909,10 +2157,9 @@ $sheet-max-width: 860px
background-attachment: fixed
>*
opacity: 0.70
// }}}
div.ui-widget-overlay
background: black
@include opacity(0.3)
// au BufWritePost,FileWritePost *.sass :!sass --style expanded --line-numbers <afile> > "%:p:r.css"
// vim:tabstop=4:shiftwidth=4:softtabstop=4:fdm=marker:
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

+2 -2
View File
@@ -24,7 +24,7 @@
init: function(modules) {
// By default only web will be loaded, the rest will be by loaded
// by openerp.web.Session on the first session_authenticate
modules = modules || ["web"];
modules = _.union(['web'], modules || []);
var new_instance = {
// links to the global openerp
_openerp: openerp,
@@ -48,7 +48,7 @@
* OpenERP Web web module split
*---------------------------------------------------------*/
openerp.web = function(session) {
var files = ["corelib","coresetup","dates","formats","chrome","data","views","search","list","form","list_editable","web_mobile","view_tree","data_export","data_import","view_editor"];
var files = ["corelib","coresetup","dates","formats","chrome","data","views","search","list","form","list_editable","web_mobile","view_tree","data_export","data_import"];
for(var i=0; i<files.length; i++) {
if(openerp.web[files[i]]) {
openerp.web[files[i]](session);
+260 -193
View File
@@ -57,9 +57,7 @@ instance.web.Dialog = instance.web.Widget.extend({
init: function (parent, options, content) {
var self = this;
this._super(parent);
if (content) {
this.$element = content instanceof $ ? content : $(content);
}
this.content_to_set = content;
this.dialog_options = {
modal: true,
destroy_on_close: true,
@@ -83,11 +81,6 @@ instance.web.Dialog = instance.web.Widget.extend({
if (options) {
_.extend(this.dialog_options, options);
}
if (this.dialog_options.autoOpen) {
this.open();
} else {
instance.web.dialog(this.$element, this.get_options());
}
},
get_options: function(options) {
var self = this,
@@ -116,27 +109,44 @@ instance.web.Dialog = instance.web.Widget.extend({
} else if (val.slice(-1) == "%") {
return Math.round(available_size / 100 * parseInt(val.slice(0, -1), 10));
} else {
return parseInt(val, 10);
return parseInt(val, 10);
}
},
renderElement: function() {
if (this.content_to_set) {
this.setElement(this.content_to_set);
} else if (this.template) {
this._super();
}
},
open: function(options) {
// TODO fme: bind window on resize
if (this.template) {
this.$element.html(this.renderElement());
}
if (! this.dialog_inited)
this.init_dialog();
var o = this.get_options(options);
instance.web.dialog(this.$element, o).dialog('open');
instance.web.dialog(this.$element, o).dialog('open');
if (o.height === 'auto' && o.max_height) {
this.$element.css({ 'max-height': o.max_height, 'overflow-y': 'auto' });
}
return this;
},
init_dialog: function(options) {
this.renderElement();
var o = this.get_options(options);
instance.web.dialog(this.$element, o);
var res = this.start();
this.dialog_inited = true;
return res;
},
close: function() {
this.$element.dialog('close');
},
on_close: function() {
if (this.__tmp_dialog_destroying)
return;
if (this.dialog_options.destroy_on_close) {
this.__tmp_dialog_closing = true;
this.destroy();
this.__tmp_dialog_closing = undefined;
}
},
on_resized: function() {
@@ -145,6 +155,11 @@ instance.web.Dialog = instance.web.Widget.extend({
_.each(this.getChildren(), function(el) {
el.destroy();
});
if (! this.__tmp_dialog_closing) {
this.__tmp_dialog_destroying = true;
this.close();
this.__tmp_dialog_destroying = undefined;
}
if (! this.isDestroyed()) {
this.$element.dialog('destroy');
}
@@ -248,13 +263,17 @@ instance.web.Loading = instance.web.Widget.extend({
// Block UI after 3s
this.long_running_timer = setTimeout(function () {
self.blocked_ui = true;
$.blockUI();
instance.web.blockUI();
}, 3000);
}
this.count += increment;
if (this.count > 0) {
this.$element.text(_.str.sprintf( _t("Loading (%d)"), this.count));
if (instance.connection.debug) {
this.$element.text(_.str.sprintf( _t("Loading (%d)"), this.count));
} else {
this.$element.text(_t("Loading"));
}
this.$element.show();
this.getParent().$element.addClass('oe_wait');
} else {
@@ -263,7 +282,7 @@ instance.web.Loading = instance.web.Widget.extend({
// Don't unblock if blocked by somebody else
if (self.blocked_ui) {
this.blocked_ui = false;
$.unblockUI();
instance.web.unblockUI();
}
this.$element.fadeOut();
this.getParent().$element.removeClass('oe_wait');
@@ -274,7 +293,7 @@ instance.web.Loading = instance.web.Widget.extend({
instance.web.DatabaseManager = instance.web.Widget.extend({
init: function(parent) {
this._super(parent);
this.unblockUIFunction = $.unblockUI;
this.unblockUIFunction = instance.web.unblockUI;
$.validator.addMethod('matches', function (s, _, re) {
return new RegExp(re).test(s);
}, _t("Invalid database name"));
@@ -341,16 +360,16 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
* from unblocking the UI
*/
blockUI: function () {
$.blockUI();
$.unblockUI = function () {};
instance.web.blockUI();
instance.web.unblockUI = function () {};
},
/**
* Reinstates $.unblockUI so third parties can play with blockUI, and
* unblocks the UI
*/
unblockUI: function () {
$.unblockUI = this.unblockUIFunction;
$.unblockUI();
instance.web.unblockUI = this.unblockUIFunction;
instance.web.unblockUI();
},
/**
* Displays an error dialog resulting from the various RPC communications
@@ -374,8 +393,19 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
var fields = $(form).serializeArray();
self.rpc("/web/database/create", {'fields': fields}, function(result) {
var form_obj = self.to_object(fields);
self.getParent().do_login( form_obj['db_name'], 'admin', form_obj['create_admin_pwd']);
self.destroy();
var client_action = {
type: 'ir.actions.client',
tag: 'login',
params: {
'db': form_obj['db_name'],
'login': 'admin',
'password': form_obj['create_admin_pwd'],
'login_successful': function() {
instance.webclient.show_application();
},
},
};
self.do_action(client_action);
});
},
@@ -460,19 +490,26 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
});
},
do_exit: function () {
this.do_action("login");
}
});
instance.web.client_actions.add("database_manager", "instance.web.DatabaseManager");
instance.web.Login = instance.web.Widget.extend({
template: "Login",
remember_credentials: true,
_db_list: null,
init: function(parent) {
init: function(parent, params) {
this._super(parent);
this.has_local_storage = typeof(localStorage) != 'undefined';
this.selected_db = null;
this.selected_login = null;
this.params = params || {};
if (this.params.login_successful) {
this.on('login_successful', this, this.params.login_successful);
}
if (this.has_local_storage && this.remember_credentials) {
this.selected_db = localStorage.getItem('last_db_login_success');
@@ -482,26 +519,17 @@ instance.web.Login = instance.web.Widget.extend({
}
}
},
open_db_manager: function(){
var self = this;
self.$element.find('.oe_login_bottom').hide();
self.$element.find('.oe_login_pane').hide();
self.databasemanager = new instance.web.DatabaseManager(self);
self.databasemanager.appendTo(self.$element);
self.databasemanager.do_exit.add_last(function() {
self.databasemanager.destroy();
self.$element.find('.oe_login_bottom').show();
self.$element.find('.oe_login_pane').show();
self.load_db_list(true).then(self.on_db_list_loaded);
});
},
start: function() {
var self = this;
self.$element.find("form").submit(self.on_submit);
self.$element.find('.oe_login_manage_db').click(function() {
self.open_db_manager();
self.do_action("database_manager");
});
return self.load_db_list().then(self.on_db_list_loaded).then(function() {
if (self.params.db) {
self.do_login(self.params.db, self.params.login, self.params.password);
}
});
return self.load_db_list().then(self.on_db_list_loaded);
},
load_db_list: function (force) {
var d = $.when(), self = this;
@@ -522,7 +550,7 @@ instance.web.Login = instance.web.Widget.extend({
var dbdiv = this.$element.find('div.oe_login_dbpane');
this.$element.find("[name=db]").replaceWith(instance.web.qweb.render('Login.dblist', { db_list: list, selected_db: this.selected_db}));
if(list.length === 0) {
self.open_db_manager();
this.do_action("database_manager");
} else if(list && list.length === 1) {
dbdiv.hide();
} else {
@@ -569,13 +597,100 @@ instance.web.Login = instance.web.Widget.extend({
localStorage.setItem('last_password_login_success', '');
}
}
self.trigger("login");
self.trigger('login_successful');
},function () {
self.$(".oe_login_pane").fadeIn("fast");
self.$element.addClass("oe_login_invalid");
});
},
show: function () {
this.$element.show();
},
hide: function () {
this.$element.hide();
}
});
instance.web.client_actions.add("login", "instance.web.Login");
/**
* Client action to reload the whole interface.
* If params has an entry 'menu_id', it opens the given menu entry.
*/
instance.web.Reload = instance.web.Widget.extend({
init: function(parent, params) {
this._super(parent);
this.menu_id = (params && params.menu_id) || false;
},
start: function() {
var l = window.location;
var timestamp = new Date().getTime();
var search = "?ts=" + timestamp;
if (l.search) {
search = l.search + "&ts=" + timestamp;
}
var hash = l.hash;
if (this.menu_id) {
hash = "#menu_id=" + this.menu_id;
}
var url = l.protocol + "//" + l.host + l.pathname + search + hash;
window.location = url;
}
});
instance.web.client_actions.add("reload", "instance.web.Reload");
/**
* Client action to go back in breadcrumb history.
* If can't go back in history stack, will go back to home.
*/
instance.web.HistoryBack = instance.web.Widget.extend({
init: function(parent, params) {
if (!parent.history_back()) {
window.location = '/' + (window.location.search || '');
}
}
});
instance.web.client_actions.add("history_back", "instance.web.HistoryBack");
/**
* Client action to go back home.
*/
instance.web.Home = instance.web.Widget.extend({
init: function(parent, params) {
window.location = '/' + (window.location.search || '');
}
});
instance.web.client_actions.add("home", "instance.web.Home");
instance.web.ChangePassword = instance.web.Widget.extend({
template: "ChangePassword",
start: function() {
var self = this;
self.$element.find("form[name=change_password_form]").validate({
submitHandler: function (form) {
self.rpc("/web/session/change_password",{
'fields': $(form).serializeArray()
}, function(result) {
if (result.error) {
self.display_error(result);
return;
} else {
instance.webclient.on_logout();
}
});
}
});
},
display_error: function (error) {
return instance.web.dialog($('<div>'), {
modal: true,
title: error.title,
buttons: [
{text: _("Ok"), click: function() { $(this).dialog("close"); }}
]
}).html(error.error);
},
})
instance.web.client_actions.add("change_password", "instance.web.ChangePassword");
instance.web.Menu = instance.web.Widget.extend({
template: 'Menu',
@@ -744,37 +859,6 @@ instance.web.UserMenu = instance.web.Widget.extend({
}
});
},
change_password :function() {
var self = this;
this.dialog = new instance.web.Dialog(this, {
title: _t("Change Password"),
width : 'auto'
}).open();
this.dialog.$element.html(QWeb.render("UserMenu.password", self));
this.dialog.$element.find("form[name=change_password_form]").validate({
submitHandler: function (form) {
self.rpc("/web/session/change_password",{
'fields': $(form).serializeArray()
}, function(result) {
if (result.error) {
self.display_error(result);
return;
} else {
instance.webclient.on_logout();
}
});
}
});
},
display_error: function (error) {
return instance.web.dialog($('<div>'), {
modal: true,
title: error.title,
buttons: [
{text: _("Ok"), click: function() { $(this).dialog("close"); }}
]
}).html(error.error);
},
do_update: function () {
var self = this;
var fct = function() {
@@ -790,7 +874,7 @@ instance.web.UserMenu = instance.web.Widget.extend({
if(res.company_id[0] > 1)
topbar_name = _.str.sprintf("%s (%s)", topbar_name, res.company_id[1]);
self.$element.find('.oe_topbar_name').text(topbar_name);
var avatar_src = _.str.sprintf('%s/web/binary/image?session_id=%s&model=res.users&field=avatar&id=%s', self.session.prefix, self.session.session_id, self.session.uid);
var avatar_src = _.str.sprintf('%s/web/binary/image?session_id=%s&model=res.users&field=image_small&id=%s', self.session.prefix, self.session.session_id, self.session.uid);
$avatar.attr('src', avatar_src);
});
};
@@ -802,44 +886,10 @@ instance.web.UserMenu = instance.web.Widget.extend({
},
on_menu_settings: function() {
var self = this;
var action_manager = new instance.web.ActionManager(this);
var dataset = new instance.web.DataSet (this,'res.users',this.context);
dataset.call ('action_get','',function (result){
self.rpc('/web/action/load', {action_id:result}, function(result){
action_manager.do_action(_.extend(result['result'], {
target: 'inline',
res_id: self.session.uid,
res_model: 'res.users',
flags: {
action_buttons: false,
search_view: false,
sidebar: false,
views_switcher: false,
pager: false
}
}));
});
self.rpc("/web/action/load", { action_id: "base.action_res_users_my" }, function(result) {
result.result.res_id = instance.connection.uid;
self.getParent().action_manager.do_action(result.result);
});
this.dialog = new instance.web.Dialog(this,{
title: _t("Preferences"),
width: '700px',
buttons: [
{text: _t("Change password"), click: function(){ self.change_password(); }},
{text: _t("Cancel"), click: function(){ $(this).dialog('destroy'); }},
{text: _t("Save"), click: function(){
var inner_widget = action_manager.inner_widget;
inner_widget.views[inner_widget.active_view].controller.do_save()
.then(function() {
self.dialog.destroy();
// needs to refresh interface in case language changed
window.location.reload();
});
}
}
]
}).open();
action_manager.appendTo(this.dialog.$element);
action_manager.renderElement(this.dialog);
},
on_menu_about: function() {
var self = this;
@@ -851,56 +901,36 @@ instance.web.UserMenu = instance.web.Widget.extend({
window.location.href, 'debug');
});
instance.web.dialog($help, {autoOpen: true,
modal: true, width: 960, title: _t("About")});
modal: true, width: 580, height: 290, resizable: false, title: _t("About")});
});
},
});
instance.web.WebClient = instance.web.Widget.extend({
init: function(parent) {
var self = this;
instance.web.Client = instance.web.Widget.extend({
init: function(parent, origin) {
instance.client = instance.webclient = this;
this._super(parent);
instance.webclient = this;
this.querystring = '?' + jQuery.param.querystring();
this._current_state = null;
},
_get_version_label: function() {
if (this.session.openerp_entreprise) {
return 'OpenERP';
} else {
return _t("OpenERP - Unsupported/Community Version");
}
},
set_title: function(title) {
title = _.str.clean(title);
var sep = _.isEmpty(title) ? '' : ' - ';
document.title = title + sep + 'OpenERP';
this.origin = origin;
},
start: function() {
var self = this;
this.$element.addClass("openerp openerp_webclient_container");
if (jQuery.param !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined) {
$("body").addClass("kitten-mode-activated");
if ($.blockUI) {
$.blockUI.defaults.message = '<img src="http://www.amigrave.com/kitten.gif">';
}
}
this.session.session_bind().then(function() {
self.destroy_content();
self.show_common();
if (!self.session.session_is_valid()) {
self.show_login();
} else {
self.show_application();
}
return instance.connection.session_bind(this.origin).pipe(function() {
var $e = $(QWeb.render(self._template, {}));
self.replaceElement($e);
self.bind_events();
return self.show_common();
});
},
bind_events: function() {
var self = this;
this.$element.on('mouseenter', '.oe_systray > div:not([data-tipsy=true])', function() {
$(this).attr('data-tipsy', 'true').tipsy().trigger('mouseenter');
});
this.$element.on('click', '.oe_dropdown_toggle', function(ev) {
ev.preventDefault();
var $toggle = $(this);
var $menu = $toggle.find('.oe_dropdown_menu');
var $menu = $toggle.siblings('.oe_dropdown_menu');
$menu = $menu.size() >= 1 ? $menu : $toggle.find('.oe_dropdown_menu');
var state = $menu.is('.oe_opened');
setTimeout(function() {
// Do not alter propagation
@@ -910,21 +940,63 @@ instance.web.WebClient = instance.web.Widget.extend({
var doc_width = $(document).width();
var offset = $menu.offset();
var menu_width = $menu.width();
var x = doc_width - offset.left - menu_width - 15;
var x = doc_width - offset.left - menu_width - 2;
if (x < 0) {
$menu.offset({ left: offset.left + x }).width(menu_width);
}
}
}, 0);
});
instance.web.bus.on('click', this, function() {
self.$element.find('.oe_dropdown_menu.oe_opened').removeClass('oe_opened');
instance.web.bus.on('click', this, function(ev) {
$.fn.tipsy.clear();
if (!$(ev.target).is('input[type=file]')) {
self.$element.find('.oe_dropdown_menu.oe_opened').removeClass('oe_opened');
}
});
},
show_common: function() {
var self = this;
this.crashmanager = new instance.web.CrashManager();
instance.connection.on_rpc_error.add(this.crashmanager.on_rpc_error);
self.notification = new instance.web.Notification(this);
self.notification.appendTo(self.$element);
self.loading = new instance.web.Loading(self);
self.loading.appendTo(self.$element);
self.action_manager = new instance.web.ActionManager(self);
self.action_manager.appendTo(self.$('.oe_application'));
},
});
instance.web.WebClient = instance.web.Client.extend({
_template: 'WebClient',
init: function(parent) {
this._super(parent);
this._current_state = null;
},
start: function() {
var self = this;
return $.when(this._super()).pipe(function() {
if (jQuery.param !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined) {
$("body").addClass("kitten-mode-activated");
if ($.blockUI) {
$.blockUI.defaults.message = '<img src="http://www.amigrave.com/kitten.gif">';
}
}
if (!self.session.session_is_valid()) {
self.show_login();
} else {
self.show_application();
}
});
},
set_title: function(title) {
title = _.str.clean(title);
var sep = _.isEmpty(title) ? '' : ' - ';
document.title = title + sep + 'OpenERP';
},
show_common: function() {
var self = this;
this._super();
window.onerror = function (message, file, line) {
self.crashmanager.on_traceback({
type: _t("Client Error"),
@@ -932,24 +1004,15 @@ instance.web.WebClient = instance.web.Widget.extend({
data: {debug: file + ':' + line}
});
};
self.notification = new instance.web.Notification(this);
self.notification.appendTo(self.$element);
self.loading = new instance.web.Loading(self);
self.loading.appendTo(self.$element);
self.login = new instance.web.Login(self);
self.login.on("login",self,self.show_application);
self.$table = $(QWeb.render("WebClient", {}));
self.action_manager = new instance.web.ActionManager(self);
self.action_manager.appendTo(self.$table.find('.oe_application'));
},
show_login: function() {
var self = this;
self.login.appendTo(self.$element);
this.$('.oe_topbar').hide();
this.action_manager.do_action("login");
this.action_manager.inner_widget.on('login_successful', this, this.show_application);
},
show_application: function() {
var self = this;
self.$element.append(self.$table);
self.login.$element.hide();
self.$('.oe_topbar').show();
self.menu = new instance.web.Menu(self);
self.menu.replace(this.$element.find('.oe_menu_placeholder'));
self.menu.on('menu_click', this, this.on_menu_action);
@@ -960,7 +1023,7 @@ instance.web.WebClient = instance.web.Widget.extend({
self.user_menu.do_update();
self.bind_hashchange();
if (!self.session.openerp_entreprise) {
var version_label = self._get_version_label();
var version_label = _t("OpenERP - Unsupported/Community Version");
self.$element.find('.oe_footer_powered').append(_.str.sprintf('<span> - <a href="http://www.openerp.com/support-or-publisher-warranty-contract" target="_blank">%s</a></span>', version_label));
}
self.set_title();
@@ -1001,15 +1064,15 @@ instance.web.WebClient = instance.web.Widget.extend({
$(window).bind('hashchange', this.on_hashchange);
var state = $.bbq.getState(true);
if (! _.isEmpty(state)) {
$(window).trigger('hashchange');
} else {
if (_.isEmpty(state) || state.action == "login") {
self.menu.has_been_loaded.then(function() {
var first_menu_id = self.menu.$element.find("a:first").data("menu");
if(first_menu_id) {
self.menu.menu_click(first_menu_id);
}
});
} else {
$(window).trigger('hashchange');
}
},
on_hashchange: function(event) {
@@ -1030,6 +1093,7 @@ instance.web.WebClient = instance.web.Widget.extend({
},
do_push_state: function(state) {
this.set_title(state.title);
delete state.title;
var url = '#' + $.param(state);
this._current_state = _.clone(state);
$.bbq.pushState(url);
@@ -1056,38 +1120,46 @@ instance.web.WebClient = instance.web.Widget.extend({
}
},
set_content_full_screen: function(fullscreen) {
if (fullscreen)
if (fullscreen) {
$(".oe_webclient", this.$element).addClass("oe_content_full_screen");
else
$("body").css({'overflow-y':'hidden'});
} else {
$(".oe_webclient", this.$element).removeClass("oe_content_full_screen");
$("body").css({'overflow-y':'scroll'});
}
}
});
instance.web.EmbeddedClient = instance.web.Widget.extend({
template: 'EmptyComponent',
init: function(parent, action_id, options) {
this._super(parent);
// TODO take the xmlid of a action instead of its id
instance.web.EmbeddedClient = instance.web.Client.extend({
_template: 'EmbedClient',
init: function(parent, origin, dbname, login, key, action_id, options) {
this._super(parent, origin);
this.dbname = dbname;
this.login = login;
this.key = key;
this.action_id = action_id;
this.options = options || {};
this.am = new instance.web.ActionManager(this);
},
start: function() {
var self = this;
this.am.appendTo(this.$element.addClass('openerp'));
return this.rpc("/web/action/load", { action_id: this.action_id }, function(result) {
var action = result.result;
action.flags = _.extend({
//views_switcher : false,
search_view : false,
action_buttons : false,
sidebar : false
//pager : false
}, self.options, action.flags || {});
return $.when(this._super()).pipe(function() {
return instance.connection.session_authenticate(self.dbname, self.login, self.key, true).pipe(function() {
return self.rpc("/web/action/load", { action_id: self.action_id }, function(result) {
var action = result.result;
action.flags = _.extend({
//views_switcher : false,
search_view : false,
action_buttons : false,
sidebar : false
//pager : false
}, self.options, action.flags || {});
self.am.do_action(action);
self.action_manager.do_action(action);
});
});
});
}
},
});
instance.web.embed = function (origin, dbname, login, key, action, options) {
@@ -1101,13 +1173,8 @@ instance.web.embed = function (origin, dbname, login, key, action, options) {
var sc = document.getElementsByTagName('script');
currentScript = sc[sc.length-1];
}
instance.connection.session_bind(origin).then(function () {
instance.connection.session_authenticate(dbname, login, key, true).then(function () {
var client = new instance.web.EmbeddedClient(null, action, options);
client.insertAfter(currentScript);
});
});
var client = new instance.web.EmbeddedClient(null, origin, dbname, login, key, action, options);
client.insertAfter(currentScript);
};
};
+135 -36
View File
@@ -378,7 +378,8 @@ instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, {
instance.web.EventDispatcherMixin.init.call(this);
this.__getterSetterInternalMap = {};
},
set: function(map) {
set: function(map, options) {
options = options || {};
var self = this;
var changed = false;
_.each(map, function(val, key) {
@@ -387,10 +388,11 @@ instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, {
return;
changed = true;
self.__getterSetterInternalMap[key] = val;
self.trigger("change:" + key, self, {
oldValue: tmp,
newValue: val
});
if (! options.silent)
self.trigger("change:" + key, self, {
oldValue: tmp,
newValue: val
});
});
if (changed)
self.trigger("change", self);
@@ -489,23 +491,19 @@ instance.web.CallbackEnabledMixin = _.extend({}, instance.web.PropertiesMixin, {
*
* The semantics of this precisely replace closing over the method call.
*
* @param {String} method_name name of the method to invoke
* @param {String|Function} method function or name of the method to invoke
* @returns {Function} proxied method
*/
proxy: function (method_name) {
proxy: function (method) {
var self = this;
return function () {
return self[method_name].apply(self, arguments);
var fn = (typeof method === 'string') ? self[method] : method;
return fn.apply(self, arguments);
}
}
});
instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, {
/**
* Tag name when creating a default $element.
* @type string
*/
tagName: 'div',
/**
* Constructs the widget and sets its parent if a parent is given.
*
@@ -515,14 +513,9 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, {
* @param {instance.web.Widget} parent Binds the current instance to the given Widget instance.
* When that widget is destroyed by calling destroy(), the current instance will be
* destroyed too. Can be null.
* @param {String} element_id Deprecated. Sets the element_id. Only useful when you want
* to bind the current Widget to an already existing part of the DOM, which is not compatible
* with the DOM insertion methods provided by the current implementation of Widget. So
* for new components this argument should not be provided any more.
*/
init: function(parent) {
instance.web.CallbackEnabledMixin.init.call(this);
this.$element = $(document.createElement(this.tagName));
this.setParent(parent);
},
/**
@@ -532,7 +525,7 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, {
_.each(this.getChildren(), function(el) {
el.destroy();
});
if(this.$element != null) {
if(this.$element) {
this.$element.remove();
}
instance.web.PropertiesMixin.destroy.call(this);
@@ -611,6 +604,7 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, {
* @returns {jQuery.Deferred}
*/
start: function() {
return $.when();
}
});
@@ -671,6 +665,12 @@ instance.web.CallbackEnabled = instance.web.Class.extend(instance.web.CallbackEn
* That will kill the widget in a clean way and erase its content from the dom.
*/
instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, {
// Backbone-ish API
tagName: 'div',
id: null,
className: null,
attributes: {},
events: {},
/**
* The name of the QWeb template that will be used for rendering. Must be
* redefined in subclasses or the default render() method can not be used.
@@ -687,13 +687,11 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, {
* @param {instance.web.Widget} parent Binds the current instance to the given Widget instance.
* When that widget is destroyed by calling destroy(), the current instance will be
* destroyed too. Can be null.
* @param {String} element_id Deprecated. Sets the element_id. Only useful when you want
* to bind the current Widget to an already existing part of the DOM, which is not compatible
* with the DOM insertion methods provided by the current implementation of Widget. So
* for new components this argument should not be provided any more.
*/
init: function(parent) {
instance.web.WidgetMixin.init.call(this,parent);
// FIXME: this should not be
this.setElement(this._make_descriptive());
this.session = instance.connection;
},
/**
@@ -702,20 +700,120 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, {
* key that references `this`.
*/
renderElement: function() {
var rendered = null;
if (this.template)
rendered = instance.web.qweb.render(this.template, {widget: this});
if (_.str.trim(rendered)) {
var elem = $(rendered);
this.$element.replaceWith(elem);
this.$element = elem;
var $el;
if (this.template) {
$el = $(_.str.trim(instance.web.qweb.render(
this.template, {widget: this})));
} else {
$el = this._make_descriptive();
}
this.replaceElement($el);
},
/**
* Re-sets the widget's root element and replaces the old root element
* (if any) by the new one in the DOM.
*
* @param {HTMLElement | jQuery} $el
* @returns {*} this
*/
replaceElement: function ($el) {
var $oldel = this.$element;
this.setElement($el);
if ($oldel && !$oldel.is(this.$element)) {
$oldel.replaceWith(this.$element);
}
return this;
},
/**
* Shortcut for $element.find() like backbone
* Re-sets the widget's root element (el/$el/$element).
*
* Includes:
* * re-delegating events
* * re-binding sub-elements
* * if the widget already had a root element, replacing the pre-existing
* element in the DOM
*
* @param {HTMLElement | jQuery} element new root element for the widget
* @return {*} this
*/
"$": function() {
return this.$element.find.apply(this.$element,arguments);
setElement: function (element) {
// NB: completely useless, as WidgetMixin#init creates a $element
// always
if (this.$element) {
this.undelegateEvents();
}
this.$element = (element instanceof $) ? element : $(element);
this.el = this.$element[0];
this.delegateEvents();
return this;
},
/**
* Utility function to build small DOM elements.
*
* @param {String} tagName name of the DOM element to create
* @param {Object} [attributes] map of DOM attributes to set on the element
* @param {String} [content] HTML content to set on the element
* @return {Element}
*/
make: function (tagName, attributes, content) {
var el = document.createElement(tagName);
if (!_.isEmpty(attributes)) {
$(el).attr(attributes);
}
if (content) {
$(el).html(content);
}
return el;
},
/**
* Makes a potential root element from the declarative builder of the
* widget
*
* @return {jQuery}
* @private
*/
_make_descriptive: function () {
var attrs = _.extend({}, this.attributes || {});
if (this.id) { attrs.id = this.id; }
if (this.className) { attrs['class'] = this.className; }
return $(this.make(this.tagName, attrs));
},
delegateEvents: function () {
var events = this.events;
if (_.isEmpty(events)) { return; }
for(var key in events) {
if (!events.hasOwnProperty(key)) { continue; }
var method = this.proxy(events[key]);
var match = /^(\S+)(\s+(.*))?$/.exec(key);
var event = match[1];
var selector = match[3];
event += '.widget_events';
if (!selector) {
this.$element.on(event, method);
} else {
this.$element.on(event, selector, method);
}
}
},
undelegateEvents: function () {
this.$element.off('.widget_events');
},
/**
* Shortcut for ``this.$element.find(selector)``
*
* @param {String} selector CSS selector, rooted in $el
* @returns {jQuery} selector match
*/
$: function(selector) {
return this.$element.find(selector);
},
/**
* Informs the action manager to do an action. This supposes that
@@ -1037,7 +1135,8 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
uid: new py.float(this.uid),
datetime: datetime,
time: time,
relativedelta: relativedelta
relativedelta: relativedelta,
current_date: date.today.__call__().strftime(['%Y-%m-%d'])
};
},
/**
@@ -1278,7 +1377,7 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
processData: false
}, url);
if (this.synch)
ajax.async = false;
ajax.async = false;
return $.ajax(ajax);
},
rpc_jsonp: function(url, payload) {
@@ -1297,7 +1396,7 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
data: data
}, url);
if (this.synch)
ajax.async = false;
ajax.async = false;
var payload_str = JSON.stringify(payload);
var payload_url = $.param({r:payload_str});
if(payload_url.length < 2000) {
+49 -44
View File
@@ -19,15 +19,14 @@ instance.web.OldWidget = instance.web.Widget.extend({
this._super(parent);
this.element_id = element_id;
this.element_id = this.element_id || _.uniqueId('widget-');
var tmp = document.getElementById(this.element_id);
this.$element = tmp ? $(tmp) : $(document.createElement(this.tagName));
this.setElement(tmp || this._make_descriptive());
},
renderElement: function() {
var rendered = this.render();
if (rendered) {
var elem = $(rendered);
this.$element.replaceWith(elem);
this.$element = elem;
this.replaceElement($(rendered));
}
return this;
},
@@ -394,13 +393,13 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
timer = setTimeout(waitLoop, CHECK_INTERVAL);
},
synchronized_mode: function(to_execute) {
var synch = this.synch;
this.synch = true;
try {
return to_execute();
} finally {
this.synch = synch;
}
var synch = this.synch;
this.synch = true;
try {
return to_execute();
} finally {
this.synch = synch;
}
}
});
@@ -416,12 +415,12 @@ instance.web.Bus = instance.web.Class.extend(instance.web.EventDispatcherMixin,
// check gtk bindings
// http://unixpapa.com/js/key.html
_.each('click,dblclick,keydown,keypress,keyup'.split(','), function(evtype) {
$('html').on(evtype, self, function(ev) {
$('html').on(evtype, function(ev) {
self.trigger(evtype, ev);
});
});
_.each('resize,scroll'.split(','), function(evtype) {
$(window).on(evtype, self, function(ev) {
$(window).on(evtype, function(ev) {
self.trigger(evtype, ev);
});
});
@@ -541,16 +540,48 @@ $.async_when = function() {
// special tweak for the web client
var old_async_when = $.async_when;
$.async_when = function() {
if (instance.connection.synch)
return $.when.apply(this, arguments);
else
return old_async_when.apply(this, arguments);
if (instance.connection.synch)
return $.when.apply(this, arguments);
else
return old_async_when.apply(this, arguments);
};
/** Setup blockui */
if ($.blockUI) {
$.blockUI.defaults.baseZ = 1100;
$.blockUI.defaults.message = '<img src="/web/static/src/img/throbber2.gif">';
$.blockUI.defaults.message = '<div class="oe_blockui_spin" style="height: 50px">';
$.blockUI.defaults.css.border = '0';
$.blockUI.defaults.css["background-color"] = '';
$.blockUI.spinners = [];
}
instance.web.blockUI = function() {
var tmp = $.blockUI.apply($, arguments);
var target = $(".oe_blockui_spin")[0];
var opts = {
lines: 13, // The number of lines to draw
length: 7, // The length of each line
width: 4, // The line thickness
radius: 10, // The radius of the inner circle
rotate: 0, // The rotation offset
color: '#FFF', // #rgb or #rrggbb
speed: 1, // Rounds per second
trail: 60, // Afterglow percentage
shadow: false, // Whether to render a shadow
hwaccel: false, // Whether to use hardware acceleration
className: 'spinner', // The CSS class to assign to the spinner
zIndex: 2e9, // The z-index (defaults to 2000000000)
top: 'auto', // Top position relative to parent in px
left: 'auto' // Left position relative to parent in px
};
var spinner = new Spinner(opts).spin(target);
$.blockUI.spinners.push(spinner);
return tmp;
}
instance.web.unblockUI = function() {
_.each($.blockUI.spinners, function(el) {
el.stop();
});
return $.unblockUI.apply($, arguments);
}
/** Setup default session */
@@ -641,32 +672,6 @@ instance.connection.on('module_loaded', this, function () {
*/
instance.web.client_actions = new instance.web.Registry();
/**
* Client action to reload the whole interface.
* If params has an entry 'menu_id', it opens the given menu entry.
*/
instance.web.Reload = instance.web.Widget.extend({
init: function(parent, params) {
this._super(parent);
this.menu_id = (params && params.menu_id) || false;
},
start: function() {
var l = window.location;
var timestamp = new Date().getTime();
var search = "?ts=" + timestamp;
if (l.search) {
search = l.search + "&ts=" + timestamp;
}
var hash = l.hash;
if (this.menu_id) {
hash = "#menu_id=" + this.menu_id;
}
var url = l.protocol + "//" + l.host + l.pathname + search + hash;
window.location = url;
}
});
instance.web.client_actions.add("reload", "instance.web.Reload");
};
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
+3 -3
View File
@@ -803,7 +803,7 @@ instance.web.DataSet = instance.web.OldWidget.extend( /** @lends openerp.web.Da
return this.ids.length;
},
alter_ids: function(n_ids) {
this.ids = n_ids;
this.ids = n_ids;
},
});
instance.web.DataSetStatic = instance.web.DataSet.extend({
@@ -1042,7 +1042,7 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({
self.cache.push({id: id, values: record});
} else {
// I assume cache value is prioritary
cached.values = _.defaults(_.clone(cached.values), record);
cached.values = _.defaults(_.clone(cached.values), record);
}
});
return_records();
@@ -1067,7 +1067,7 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({
return this._super(method, args, callback, error_callback);
},
alter_ids: function(n_ids) {
this._super(n_ids);
this._super(n_ids);
this.on_change();
},
});
+2 -2
View File
@@ -376,7 +376,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
exported_fields.unshift({name: 'id', label: 'External ID'});
var export_format = this.$element.find("#export_format").val();
$.blockUI();
instance.web.blockUI();
this.session.get_file({
url: '/web/export/' + export_format,
data: {data: JSON.stringify({
@@ -387,7 +387,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
import_compat: Boolean(
this.$element.find("#import_compat").val())
})},
complete: $.unblockUI
complete: instance.web.unblockUI
});
},
close: function() {
+1 -1
View File
@@ -156,7 +156,7 @@ instance.web.DataImport = instance.web.Dialog.extend({
});
},
toggle_import_button: function (newstate) {
instance.web.dialog(this.$element, 'widget')
instance.web.dialog(this.$element, 'widget')
.find('.oe_import_dialog_button')
.button('option', 'disabled', !newstate);
},
-78
View File
@@ -271,82 +271,4 @@ instance.web.auto_date_to_str = function(value, type) {
}
};
/**
* Formats a provided cell based on its field type. Most of the field types
* return a correctly formatted value, but some tags and fields are
* special-cased in their handling:
*
* * buttons will return an actual ``<button>`` tag with a bunch of error handling
*
* * boolean fields will return a checkbox input, potentially disabled
*
* * binary fields will return a link to download the binary data as a file
*
* @param {Object} row_data record whose values should be displayed in the cell
* @param {Object} column column descriptor
* @param {"button"|"field"} column.tag base control type
* @param {String} column.type widget type for a field control
* @param {String} [column.string] button label
* @param {String} [column.icon] button icon
* @param {Object} [options]
* @param {String} [options.value_if_empty=''] what to display if the field's value is ``false``
* @param {Boolean} [options.process_modifiers=true] should the modifiers be computed ?
* @param {String} [options.model] current record's model
* @param {Number} [options.id] current record's id
*
*/
instance.web.format_cell = function (row_data, column, options) {
options = options || {};
var attrs = {};
if (options.process_modifiers !== false) {
attrs = column.modifiers_for(row_data);
}
if (attrs.invisible) { return ''; }
if (column.tag === 'button') {
return _.template('<button type="button" title="<%-title%>" <%=additional_attributes%> >' +
'<img src="<%-prefix%>/web/static/src/img/icons/<%-icon%>.png" alt="<%-alt%>"/>' +
'</button>', {
title: column.string || '',
additional_attributes: isNaN(row_data["id"].value) && instance.web.BufferedDataSet.virtual_id_regex.test(row_data["id"].value) ?
'disabled="disabled" class="oe_list_button_disabled"' : '',
prefix: instance.connection.prefix,
icon: column.icon,
alt: column.string || ''
});
}
if (!row_data[column.id]) {
return options.value_if_empty === undefined ? '' : options.value_if_empty;
}
switch (column.widget || column.type) {
case "boolean":
return _.str.sprintf('<input type="checkbox" %s disabled="disabled"/>',
row_data[column.id].value ? 'checked="checked"' : '');
case "binary":
var text = _t("Download"),
download_url = _.str.sprintf('/web/binary/saveas?session_id=%s&model=%s&field=%s&id=%d', instance.connection.session_id, options.model, column.id, options.id);
if (column.filename) {
download_url += '&filename_field=' + column.filename;
if (row_data[column.filename]) {
text = _.str.sprintf(_t("Download \"%s\""), instance.web.format_value(
row_data[column.filename].value, {type: 'char'}));
}
}
return _.template('<a href="<%-href%>"><%-text%></a> (%<-size%>)', {
text: text,
href: download_url,
size: row_data[column.id].value
});
case 'progressbar':
return _.template(
'<progress value="<%-value%>" max="100"><%-value%>%</progress>', {
value: _.str.sprintf("%.0f", row_data[column.id].value || 0)
});
}
return _.escape(instance.web.format_value(
row_data[column.id].value, column, options.value_if_empty));
}
};
+57 -34
View File
@@ -330,6 +330,12 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
});
}
// Launch a search on clicking the oe_searchview_search button
this.$element.on('click', 'button.oe_searchview_search', function (e) {
e.stopImmediatePropagation();
self.do_search();
});
this.$element.on('keydown',
'.oe_searchview_input, .oe_searchview_facet', function (e) {
switch(e.which) {
@@ -510,7 +516,16 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
this.$element.addClass('oe_focused');
},
childBlurred: function () {
this.$element.removeClass('oe_focused');
var val = this.$element.val();
this.$element.val('');
var complete = this.$element.data('autocomplete');
if ((val && complete.term === undefined) || complete.previous !== undefined) {
throw new Error("new jquery.ui version altering implementation" +
" details relied on");
}
delete complete.term;
this.$element.removeClass('oe_focused')
.trigger('blur');
},
/**
*
@@ -646,7 +661,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
null, _(this.select_for_drawer()).invoke(
'appendTo', this.$element.find('.oe_searchview_drawer')));
new instance.web.search.AddToDashboard(this).appendTo($('.oe_searchview_drawer', this.$element));
new instance.web.search.AddToReporting(this).appendTo($('.oe_searchview_drawer', this.$element));
// load defaults
var defaults_fetched = $.when.apply(null, _(this.inputs).invoke(
@@ -846,13 +861,13 @@ instance.web.search.Invalid = instance.web.Class.extend( /** @lends instance.web
);
}
});
instance.web.search.Widget = instance.web.OldWidget.extend( /** @lends instance.web.search.Widget# */{
instance.web.search.Widget = instance.web.Widget.extend( /** @lends instance.web.search.Widget# */{
template: null,
/**
* Root class of all search widgets
*
* @constructs instance.web.search.Widget
* @extends instance.web.OldWidget
* @extends instance.web.Widget
*
* @param view the ancestor view of this widget
*/
@@ -1475,7 +1490,17 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
facet_for: function (value) {
var self = this;
if (value instanceof Array) {
return $.when(facet_from(this, value));
if (value.length === 2 && _.isString(value[1])) {
return $.when(facet_from(this, value));
}
if (value.length > 1) {
// more than one search_default m2o id? Should we OR them?
throw new Error(
_("M2O search fields do not currently handle multiple default values"));
}
// there are many cases of {search_default_$m2ofield: [id]}, need
// to handle this as if it were a single value.
value = value[0];
}
return this.model.call('name_get', [value], {}).pipe(function (names) {
if (_(names).isEmpty()) { return null; }
@@ -1653,41 +1678,39 @@ instance.web.search.Filters = instance.web.search.Input.extend({
}));
}
});
instance.web.search.AddToDashboard = instance.web.Widget.extend({
template: 'SearchView.addtodashboard',
instance.web.search.AddToReporting = instance.web.Widget.extend({
template: 'SearchView.addtoreporting',
_in_drawer: true,
start: function () {
var self = this;
this.data_loaded = $.Deferred();
this.dashboard_data =[];
this.$element
.on('click', 'h4', this.proxy('show_option'))
.on('submit', 'form', function (e) {
e.preventDefault();
self.add_dashboard();
});
return $.when(this.load_data(),this.data_loaded).pipe(this.proxy("render_data"));
return this.load_data().then(this.proxy("render_data"));
},
load_data:function(){
var self = this,dashboard_menu = instance.webclient.menu.data.data.children;
var ir_model_data = new instance.web.Model('ir.model.data',{},[['name','=','menu_reporting_dashboard']]).query(['res_id']);
var map_data = function(result){
_.detect(dashboard_menu, function(dash){
var id = _.pluck(dash.children, "id"),indexof = _.indexOf(id, result.res_id);
if(indexof !== -1){
self.dashboard_data = dash.children[indexof].children
self.data_loaded.resolve();
return;
}
});
};
return ir_model_data._execute().done(function(result){map_data(result[0])});
if (!instance.webclient) { return $.Deferred().reject(); }
var dashboard_menu = instance.webclient.menu.data.data.children;
return new instance.web.Model('ir.model.data')
.query(['res_id'])
.filter([['name','=','menu_reporting_dashboard']])
.first().pipe(function (result) {
var menu = _(dashboard_menu).chain()
.pluck('children')
.flatten(true)
.find(function (child) { return child.id === result.res_id; })
.value();
return menu ? menu.children : [];
});
},
render_data: function(){
var self = this;
var selection = instance.web.qweb.render("SearchView.addtodashboard.selection",{selections:this.dashboard_data});
this.$element.find("input").before(selection)
render_data: function(dashboard_choices){
var selection = instance.web.qweb.render(
"SearchView.addtoreporting.selection", {
selections: dashboard_choices});
this.$("input").before(selection)
},
add_dashboard:function(){
var self = this;
@@ -1695,11 +1718,11 @@ instance.web.search.AddToDashboard = instance.web.Widget.extend({
var view_parent = this.getParent().getParent();
if (! view_parent.action || ! this.$element.find("select").val())
return this.do_warn("Can't find dashboard action");
data = getParent.build_search_data(),
context = new instance.web.CompoundContext(getParent.dataset.get_context() || []),
domain = new instance.web.CompoundDomain(getParent.dataset.get_domain() || []);
_.each(data.contexts, function(x) {context.add(x);});
_.each(data.domains, function(x) {domain.add(x);});
var data = getParent.build_search_data();
var context = new instance.web.CompoundContext(getParent.dataset.get_context() || []);
var domain = new instance.web.CompoundDomain(getParent.dataset.get_domain() || []);
_.each(data.contexts, context.add, context);
_.each(data.domains, domain.add, domain);
this.rpc('/web/searchview/add_to_dashboard', {
menu_id: this.$element.find("select").val(),
action_id: view_parent.action.id,
@@ -1720,7 +1743,7 @@ instance.web.search.AddToDashboard = instance.web.Widget.extend({
this.$element.toggleClass('oe_opened');
if (! this.$element.hasClass('oe_opened'))
return;
this.$element.find("input").val(this.getParent().fields_view.name || "" );
this.$("input").val(this.getParent().fields_view.name || "" );
}
});
File diff suppressed because it is too large Load Diff
+370 -132
View File
@@ -21,9 +21,6 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
// whether the view rows can be reordered (via vertical drag & drop)
'reorderable': true,
'action_buttons': true,
// if true, the view can't be editable, ignoring the view's and the context's
// instructions
'read_only': false,
// if true, the 'Import', 'Export', etc... buttons will be shown
'import_enabled': true,
},
@@ -142,7 +139,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
});
},
/**
* View startup method, the default behavior is to set the ``oe_listw``
* View startup method, the default behavior is to set the ``oe_list``
* class on its root element and to perform an RPC load call.
*
* @returns {$.Deferred} loading promise
@@ -288,7 +285,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
}
this.$buttons.find('.oe_list_add')
.click(this.proxy('do_add_record'))
.prop('disabled', grouped && this.options.editable);
.prop('disabled', grouped);
this.$buttons.on('click', '.oe_list_button_import', function() {
self.on_sidebar_import();
return false;
@@ -357,9 +354,10 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
this.sidebar.add_items('other', [
{ label: _t("Import"), callback: this.on_sidebar_import },
{ label: _t("Export"), callback: this.on_sidebar_export },
{ label: _t('Delete'), callback: this.do_delete_selected },
{ label: _t('Delete'), callback: this.do_delete_selected }
]);
this.sidebar.add_toolbar(this.fields_view.toolbar);
this.sidebar.$element.hide();
}
},
/**
@@ -378,6 +376,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
var total = dataset.size();
var limit = this.limit() || total;
this.$pager.toggle(total !== 0);
this.$pager.toggleClass('oe_list_pager_single_page', (total <= limit));
var spager = '-';
if (total) {
@@ -400,68 +399,23 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
* @param {Boolean} [grouped] Should the grouping columns (group and count) be displayed
*/
setup_columns: function (fields, grouped) {
var domain_computer = instance.web.form.compute_domain;
var noop = function () { return {}; };
var field_to_column = function (field) {
var name = field.attrs.name;
var column = _.extend({id: name, tag: field.tag},
fields[name], field.attrs);
// modifiers computer
if (column.modifiers) {
var modifiers = JSON.parse(column.modifiers);
column.modifiers_for = function (fields) {
if (!modifiers.invisible) {
return {};
}
return {
'invisible': domain_computer(modifiers.invisible, fields)
};
};
if (modifiers['tree_invisible']) {
column.invisible = '1';
} else {
delete column.invisible;
}
} else {
column.modifiers_for = noop;
}
return column;
};
var registry = instance.web.list.columns;
this.columns.splice(0, this.columns.length);
this.columns.push.apply(
this.columns,
_(this.fields_view.arch.children).map(field_to_column));
this.columns.push.apply(this.columns,
_(this.fields_view.arch.children).map(function (field) {
var id = field.attrs.name;
return registry.for_(id, fields[id], field);
}));
if (grouped) {
this.columns.unshift({
id: '_group', tag: '', string: _t("Group"), meta: true,
modifiers_for: function () { return {}; }
}, {
id: '_count', tag: '', string: '#', meta: true,
modifiers_for: function () { return {}; }
});
this.columns.unshift(
new instance.web.list.MetaColumn('_group', _t("Group")));
}
this.visible_columns = _.filter(this.columns, function (column) {
return column.invisible !== '1';
});
this.aggregate_columns = _(this.visible_columns)
.map(function (column) {
if (column.type !== 'integer' && column.type !== 'float') {
return {};
}
var aggregation_func = column['group_operator'] || 'sum';
if (!(aggregation_func in column)) {
return {};
}
return _.extend({}, column, {
'function': aggregation_func,
label: column[aggregation_func]
});
});
this.aggregate_columns = _(this.visible_columns).invoke('to_aggregate');
},
/**
* Used to handle a click on a table row, if no other handler caught the
@@ -487,9 +441,6 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
},
do_show: function () {
this._super();
if (this.sidebar) {
this.sidebar.$element.show();
}
if (this.$buttons) {
this.$buttons.show();
}
@@ -667,6 +618,23 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
* @param {Function} callback should be called after the action is executed, if non-null
*/
do_button_action: function (name, id, callback) {
this.handle_button(name, id, callback);
},
/**
* Base handling of buttons, can be called when overriding do_button_action
* in order to bypass parent overrides.
*
* The callback will be provided with the ``id`` as its parameter, in case
* handle_button's caller had to alter the ``id`` (or even create one)
* while not being ``callback``'s creator.
*
* This method should not be overridden.
*
* @param {String} name action name
* @param {Object} id id of the record the action should be called on
* @param {Function} callback should be called after the action is executed, if non-null
*/
handle_button: function (name, id, callback) {
var action = _.detect(this.columns, function (field) {
return field.name === name;
});
@@ -685,7 +653,8 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
c.add(action.context);
}
action.context = c;
this.do_execute_action(action, this.dataset, id, callback);
this.do_execute_action(
action, this.dataset, id, _.bind(callback, null, id));
},
/**
* Handles the activation of a record (clicking on it)
@@ -801,9 +770,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
}
$footer_cells.filter(_.str.sprintf('[data-field=%s]', column.id))
.html(instance.web.format_cell(aggregation, column, {
process_modifiers: false
}));
.html(column.format(aggregation, { process_modifiers: false }));
});
},
get_selected_ids: function() {
@@ -862,9 +829,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
}
this.$element.find('table:first').hide();
this.$element.prepend(
$('<div class="oe_view_nocontent">')
.append($('<img>', { src: '/web/static/src/img/view_empty_arrow.png' }))
.append($('<div>').html(this.options.action.help))
$('<div class="oe_view_nocontent">').html(this.options.action.help)
);
}
});
@@ -911,32 +876,44 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
this.record_callbacks = {
'remove': function (event, record) {
var $row = self.$current.find(
'[data-id=' + record.get('id') + ']');
var $row = self.$current.children(
'[data-id=' + record.get('id') + ']');
var index = $row.data('index');
$row.remove();
self.refresh_zebra(index);
},
'reset': function () { return self.on_records_reset(); },
'change': function (event, record) {
var $row = self.$current.find('[data-id=' + record.get('id') + ']');
'change': function (event, record, attribute, value, old_value) {
var $row;
if (attribute === 'id') {
if (old_value) {
throw new Error("Setting 'id' attribute on existing record "
+ JSON.stringify(record.attributes));
}
if (!_.contains(self.dataset.ids, value)) {
// add record to dataset if not already in (added by
// the form view?)
self.dataset.ids.splice(
self.records.indexOf(record), 0, value);
}
// Set id on new record
$row = self.$current.children('[data-id=false]');
} else {
$row = self.$current.children(
'[data-id=' + record.get('id') + ']');
}
$row.replaceWith(self.render_record(record));
},
'add': function (ev, records, record, index) {
var $new_row = $('<tr>').attr({
'data-id': record.get('id')
});
var $new_row = $(self.render_record(record));
if (index === 0) {
$new_row.prependTo(self.$current);
} else {
var previous_record = records.at(index-1),
$previous_sibling = self.$current.find(
$previous_sibling = self.$current.children(
'[data-id=' + previous_record.get('id') + ']');
$new_row.insertAfter($previous_sibling);
}
self.refresh_zebra(index, 1);
}
};
_(this.record_callbacks).each(function (callback, event) {
@@ -967,19 +944,19 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
// of digits, nice when storing actual numbers, not nice when
// storing strings composed only of digits. Force the action
// name to be a string
$(self).trigger('action', [field.toString(), record_id, function () {
return self.reload_record(self.records.get(record_id));
$(self).trigger('action', [field.toString(), record_id, function (id) {
return self.reload_record(self.records.get(id));
}]);
})
.delegate('a', 'click', function (e) {
e.stopPropagation();
})
.delegate('tr', 'click', function (e) {
e.stopPropagation();
var row_id = self.row_id(e.currentTarget);
if (row_id !== undefined) {
if (row_id) {
e.stopPropagation();
if (!self.dataset.select_id(row_id)) {
throw "Could not find id in dataset"
throw new Error("Could not find id in dataset");
}
self.row_clicked(e);
}
@@ -1029,7 +1006,7 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
});
}
}
return instance.web.format_cell(record.toForm().data, column, {
return column.format(record.toForm().data, {
model: this.dataset.model,
id: record.get('id')
});
@@ -1076,7 +1053,6 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
this.$current
.children('tr:not([data-id])').remove().end()
.append(new Array(count - this.records.length + 1).join(row));
this.refresh_zebra(this.records.length);
},
/**
* Gets the ids of all currently selected records, if any
@@ -1139,6 +1115,7 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
* @returns {String} QWeb rendering of the selected record
*/
render_record: function (record) {
var self = this;
var index = this.records.indexOf(record);
return QWeb.render('ListView.row', {
columns: this.columns,
@@ -1147,26 +1124,7 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
row_parity: (index % 2 === 0) ? 'even' : 'odd',
view: this.view,
render_cell: function () {
return this.render_cell.apply(this, arguments); }
});
},
/**
* Fixes fixes the even/odd classes
*
* @param {Number} [from_index] index from which to resequence
* @param {Number} [offset = 0] selection offset for DOM, in case there are rows to ignore in the table
*/
refresh_zebra: function (from_index, offset) {
offset = offset || 0;
from_index = from_index || 0;
var dom_offset = offset + from_index;
var sel = dom_offset ? ':gt(' + (dom_offset - 1) + ')' : null;
this.$current.children(sel).each(function (i, e) {
var index = from_index + i;
// reset record-index accelerators on rows and even/odd
var even = index%2 === 0;
$(e).toggleClass('even', even)
.toggleClass('odd', !even);
return self.render_cell.apply(self, arguments); }
});
}
});
@@ -1333,15 +1291,18 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
_t("Grouping on field '%s' is not possible because that field does not appear in the list view."),
group.grouped_on));
}
var group_label;
try {
$group_column.html(instance.web.format_cell(
row_data, group_column, {
value_if_empty: _t("Undefined"),
process_modifiers: false
}));
group_label = group_column.format(row_data, {
value_if_empty: _t("Undefined"),
process_modifiers: false
});
} catch (e) {
$group_column.html(row_data[group_column.id].value);
group_label = row_data[group_column.id].value;
}
$group_column.text(_.str.sprintf("%s (%d)",
group_label, group.length));
if (group.length && group.openable) {
// Make openable if not terminal group & group_by_no_leaf
$group_column.prepend('<span class="ui-icon ui-icon-triangle-1-e" style="float: left;">');
@@ -1353,14 +1314,12 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
}
}
self.indent($group_column, group.level);
// count column
$('<td>').text(group.length).appendTo($row);
if (self.options.selectable) {
$row.append('<td>');
}
_(self.columns).chain()
.filter(function (column) {return !column.invisible;})
.filter(function (column) { return column.invisible !== '1'; })
.each(function (column) {
if (column.meta) {
// do not do anything
@@ -1368,8 +1327,7 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
var r = {};
r[column.id] = {value: group.aggregates[column.id]};
$('<td class="oe_number">')
.html(instance.web.format_cell(
r, column, {process_modifiers: false}))
.html(column.format(r, {process_modifiers: false}))
.appendTo($row);
} else {
$row.append('<td>');
@@ -1456,18 +1414,31 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
},
setup_resequence_rows: function (list, dataset) {
// drag and drop enabled if list is not sorted and there is a
// "sequence" column in the view.
// visible column with @widget=handle or "sequence" column in the view.
if ((dataset.sort && dataset.sort())
|| !_(this.columns).any(function (column) {
return column.name === 'sequence'; })) {
return column.widget === 'handle'
|| column.name === 'sequence'; })) {
return;
}
var sequence_field = _(this.columns).find(function (c) {
return c.widget === 'handle';
});
var seqname = sequence_field ? sequence_field.name : 'sequence';
// ondrop, move relevant record & fix sequences
list.$current.sortable({
axis: 'y',
items: '> tr[data-id]',
containment: 'parent',
helper: 'clone',
helper: 'clone'
});
if (sequence_field) {
list.$current.sortable('option', 'handle', '.oe_list_field_handle');
}
list.$current.sortable('option', {
start: function (e, ui) {
ui.placeholder.height(ui.item.height());
},
stop: function (event, ui) {
var to_move = list.records.get(ui.item.data('id')),
target_id = ui.item.prev().data('id'),
@@ -1485,7 +1456,7 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
var record, index = to,
// if drag to 1st row (to = 0), start sequencing from 0
// (exclusive lower bound)
seq = to ? list.records.at(to - 1).get('sequence') : 0;
seq = to ? list.records.at(to - 1).get(seqname) : 0;
while (++seq, record = list.records.at(index++)) {
// write are independent from one another, so we can just
// launch them all at the same time and we don't really
@@ -1495,13 +1466,13 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
// when synchronous (without setTimeout)
(function (dataset, id, seq) {
$.async_when().then(function () {
dataset.write(id, {sequence: seq});
var attrs = {};
attrs[seqname] = seq;
dataset.write(id, attrs);
});
}(dataset, record.get('id'), seq));
record.set('sequence', seq);
record.set(seqname, seq);
}
list.refresh_zebra();
}
});
},
@@ -1831,7 +1802,7 @@ var Collection = instance.web.Class.extend(/** @lends Collection# */{
* @returns this
*/
remove: function (record) {
var index = _(this.records).indexOf(record);
var index = this.indexOf(record);
if (index === -1) {
_(this._proxies).each(function (proxy) {
proxy.remove(record);
@@ -1847,13 +1818,42 @@ var Collection = instance.web.Class.extend(/** @lends Collection# */{
return this;
},
_onRecordEvent: function (event, record, options) {
_onRecordEvent: function (event) {
switch(event) {
// don't propagate reset events
if (event === 'reset') { return; }
case 'reset': return;
case 'change:id':
var record = arguments[1];
var new_value = arguments[2];
var old_value = arguments[3];
// [change:id, record, new_value, old_value]
if (this._byId[old_value] === record) {
delete this._byId[old_value];
this._byId[new_value] = record;
}
break;
}
this.trigger.apply(this, arguments);
},
// underscore-type methods
find: function (callback) {
var record;
for(var section in this._proxies) {
if (!this._proxies.hasOwnProperty(section)) {
continue
}
if ((record = this._proxies[section].find(callback))) {
return record;
}
}
for(var i=0; i<this.length; ++i) {
record = this.records[i];
if (callback(record)) {
return record;
}
}
},
each: function (callback) {
for(var section in this._proxies) {
if (this._proxies.hasOwnProperty(section)) {
@@ -1878,6 +1878,46 @@ var Collection = instance.web.Class.extend(/** @lends Collection# */{
},
indexOf: function (record) {
return _(this.records).indexOf(record);
},
succ: function (record, options) {
options = options || {wraparound: false};
var result;
for(var section in this._proxies) {
if (!this._proxies.hasOwnProperty(section)) {
continue;
}
if ((result = this._proxies[section].succ(record, options))) {
return result;
}
}
var index = this.indexOf(record);
if (index === -1) { return null; }
var next_index = index + 1;
if (options.wraparound && (next_index === this.length)) {
return this.at(0);
}
return this.at(next_index);
},
pred: function (record, options) {
options = options || {wraparound: false};
var result;
for (var section in this._proxies) {
if (!this._proxies.hasOwnProperty(section)) {
continue;
}
if ((result = this._proxies[section].pred(record, options))) {
return result;
}
}
var index = this.indexOf(record);
if (index === -1) { return null; }
var next_index = index - 1;
if (options.wraparound && (next_index === -1)) {
return this.at(this.length - 1);
}
return this.at(next_index);
}
});
Collection.include(Events);
@@ -1885,6 +1925,204 @@ instance.web.list = {
Events: Events,
Record: Record,
Collection: Collection
}
};
/**
* Registry for column objects used to format table cells (and some other tasks
* e.g. aggregation computations).
*
* Maps a field or button to a Column type via its ``$tag.$widget``,
* ``$tag.$type`` or its ``$tag`` (alone).
*
* This specific registry has a dedicated utility method ``for_`` taking a
* field (from fields_get/fields_view_get.field) and a node (from a view) and
* returning the right object *already instantiated from the data provided*.
*
* @type {instance.web.Registry}
*/
instance.web.list.columns = new instance.web.Registry({
'field': 'instance.web.list.Column',
'field.boolean': 'instance.web.list.Boolean',
'field.binary': 'instance.web.list.Binary',
'field.progressbar': 'instance.web.list.ProgressBar',
'field.handle': 'instance.web.list.Handle',
'button': 'instance.web.list.Button',
});
instance.web.list.columns.for_ = function (id, field, node) {
var description = _.extend({tag: node.tag}, field, node.attrs);
var tag = description.tag;
var Type = this.get_any([
tag + '.' + description.widget,
tag + '.'+ description.type,
tag
]);
return new Type(id, node.tag, description)
};
instance.web.list.Column = instance.web.Class.extend({
init: function (id, tag, attrs) {
_.extend(attrs, {
id: id,
tag: tag
});
this.modifiers = attrs.modifiers ? JSON.parse(attrs.modifiers) : {};
delete attrs.modifiers;
_.extend(this, attrs);
if (this.modifiers['tree_invisible']) {
this.invisible = '1';
} else { delete this.invisible; }
},
modifiers_for: function (fields) {
var out = {};
var domain_computer = instance.web.form.compute_domain;
for (var attr in this.modifiers) {
if (!this.modifiers.hasOwnProperty(attr)) { continue; }
var modifier = this.modifiers[attr];
out[attr] = _.isBoolean(modifier)
? modifier
: domain_computer(modifier, fields);
}
return out;
},
to_aggregate: function () {
if (this.type !== 'integer' && this.type !== 'float') {
return {};
}
var aggregation_func = this['group_operator'] || 'sum';
if (!(aggregation_func in this)) {
return {};
}
var C = function (label, fn) {
this['function'] = fn;
this.label = label;
};
C.prototype = this;
return new C(aggregation_func, this[aggregation_func]);
},
/**
*
* @param row_data record whose values should be displayed in the cell
* @param {Object} [options]
* @param {String} [options.value_if_empty=''] what to display if the field's value is ``false``
* @param {Boolean} [options.process_modifiers=true] should the modifiers be computed ?
* @param {String} [options.model] current record's model
* @param {Number} [options.id] current record's id
* @return {String}
*/
format: function (row_data, options) {
options = options || {};
var attrs = {};
if (options.process_modifiers !== false) {
attrs = this.modifiers_for(row_data);
}
if (attrs.invisible) { return ''; }
if (!row_data[this.id]) {
return options.value_if_empty === undefined
? ''
: options.value_if_empty;
}
return this._format(row_data, options);
},
/**
* Method to override in order to provide alternative HTML content for the
* cell. Column._format will simply call ``instance.web.format_value`` and
* escape the output.
*
* The output of ``_format`` will *not* be escaped by ``format``, any
* escaping *must be done* by ``format``.
*
* @private
*/
_format: function (row_data, options) {
return _.escape(instance.web.format_value(
row_data[this.id].value, this, options.value_if_empty));
}
});
instance.web.list.MetaColumn = instance.web.list.Column.extend({
meta: true,
init: function (id, string) {
this._super(id, '', {string: string});
}
});
instance.web.list.Button = instance.web.list.Column.extend({
/**
* Return an actual ``<button>`` tag
*/
format: function (row_data, options) {
return _.template('<button type="button" title="<%-title%>" <%=additional_attributes%> >' +
'<img src="<%-prefix%>/web/static/src/img/icons/<%-icon%>.png" alt="<%-alt%>"/>' +
'</button>', {
title: this.string || '',
additional_attributes: isNaN(row_data["id"].value) && instance.web.BufferedDataSet.virtual_id_regex.test(row_data["id"].value) ?
'disabled="disabled" class="oe_list_button_disabled"' : '',
prefix: instance.connection.prefix,
icon: this.icon,
alt: this.string || ''
});
}
});
instance.web.list.Boolean = instance.web.list.Column.extend({
/**
* Return a potentially disabled checkbox input
*
* @private
*/
_format: function (row_data, options) {
return _.str.sprintf('<input type="checkbox" %s disabled="disabled"/>',
row_data[this.id].value ? 'checked="checked"' : '');
}
});
instance.web.list.Binary = instance.web.list.Column.extend({
/**
* Return a link to the binary data as a file
*
* @private
*/
_format: function (row_data, options) {
var text = _t("Download");
var download_url = _.str.sprintf(
'/web/binary/saveas?session_id=%s&model=%s&field=%s&id=%d',
instance.connection.session_id, options.model, this.id, options.id);
if (this.filename) {
download_url += '&filename_field=' + this.filename;
if (row_data[this.filename]) {
text = _.str.sprintf(_t("Download \"%s\""), instance.web.format_value(
row_data[this.filename].value, {type: 'char'}));
}
}
return _.template('<a href="<%-href%>"><%-text%></a> (%<-size%>)', {
text: text,
href: download_url,
size: row_data[this.id].value
});
}
});
instance.web.list.ProgressBar = instance.web.list.Column.extend({
/**
* Return a formatted progress bar display
*
* @private
*/
_format: function (row_data, options) {
return _.template(
'<progress value="<%-value%>" max="100"><%-value%>%</progress>', {
value: _.str.sprintf("%.0f", row_data[this.id].value || 0)
});
}
});
instance.web.list.Handle = instance.web.list.Column.extend({
/**
* Return styling hooks for a drag handle
*
* @private
*/
_format: function (row_data, options) {
return '<div class="oe_list_handle">';
}
});
};
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
File diff suppressed because it is too large Load Diff
+165 -125
View File
@@ -14,6 +14,9 @@ instance.web.ActionManager = instance.web.Widget.extend({
this.dialog = null;
this.dialog_widget = null;
this.breadcrumbs = [];
this.on('history_back', this, function() {
return this.history_back();
});
},
start: function() {
this._super.apply(this, arguments);
@@ -65,21 +68,46 @@ instance.web.ActionManager = instance.web.Widget.extend({
item.id = _.uniqueId('breadcrumb_');
this.breadcrumbs.push(item);
},
history_back: function() {
var last = this.breadcrumbs.slice(-1)[0];
if (!last) {
return false;
}
var title = last.get_title();
if (_.isArray(title) && title.length > 1) {
return this.select_breadcrumb(this.breadcrumbs.length - 1, title.length - 2);
} else if (this.breadcrumbs.length === 1) {
// Only one single titled item in breadcrumb, most of the time you want to trigger back to home
return false;
} else {
var prev = this.breadcrumbs[this.breadcrumbs.length - 2];
title = prev.get_title();
return this.select_breadcrumb(this.breadcrumbs.length - 2, _.isArray(title) ? title.length - 1 : undefined);
}
},
on_breadcrumb_clicked: function(ev) {
var $e = $(ev.target);
var id = $e.data('id');
var item;
var index;
for (var i = this.breadcrumbs.length - 1; i >= 0; i--) {
var it = this.breadcrumbs[i];
if (it.id == id) {
item = it;
if (this.breadcrumbs[i].id == id) {
index = i;
break;
}
this.remove_breadcrumb(i);
}
var index = $e.parent().find('.oe_breadcrumb_item[data-id=' + $e.data('id') + ']').index($e);
item.show(index, $e);
var subindex = $e.parent().find('.oe_breadcrumb_item[data-id=' + $e.data('id') + ']').index($e);
this.select_breadcrumb(index, subindex);
},
select_breadcrumb: function(index, subindex) {
for (var i = this.breadcrumbs.length - 1; i >= 0; i--) {
if (i > index) {
this.remove_breadcrumb(i);
}
}
var item = this.breadcrumbs[index];
item.show(subindex);
this.inner_widget = item.widget;
return true;
},
clear_breadcrumbs: function() {
while (this.breadcrumbs.length) {
@@ -114,15 +142,21 @@ instance.web.ActionManager = instance.web.Widget.extend({
}
}
}
return titles.join(' / ');
return titles.join(' <span class="oe_fade">/</span> ');
},
do_push_state: function(state) {
state = state || {};
if (this.getParent() && this.getParent().do_push_state) {
if (this.inner_action) {
state['title'] = this.inner_action.name;
state['model'] = this.inner_action.res_model;
if(this.inner_action.type == 'ir.actions.act_window') {
state['model'] = this.inner_action.res_model;
}
if (this.inner_action.id) {
state['action_id'] = this.inner_action.id;
state['action'] = this.inner_action.id;
} else if (this.inner_action.type == 'ir.actions.client') {
state['action'] = this.inner_action.tag;
//state = _.extend(this.inner_action.params || {}, state);
}
}
this.getParent().do_push_state(state);
@@ -131,14 +165,20 @@ instance.web.ActionManager = instance.web.Widget.extend({
do_load_state: function(state, warm) {
var self = this,
action_loaded;
if (state.action_id) {
var run_action = (!this.inner_widget || !this.inner_widget.action) || this.inner_widget.action.id !== state.action_id;
if (run_action) {
if (state.action) {
if (_.isString(state.action) && instance.web.client_actions.contains(state.action)) {
var action_client = {type: "ir.actions.client", tag: state.action, params: state};
this.null_action();
action_loaded = this.do_action(state.action_id);
instance.webclient.menu.has_been_loaded.then(function() {
instance.webclient.menu.open_action(state.action_id);
});
action_loaded = this.do_action(action_client);
} else {
var run_action = (!this.inner_widget || !this.inner_widget.action) || this.inner_widget.action.id !== state.action;
if (run_action) {
this.null_action();
action_loaded = this.do_action(state.action);
instance.webclient.menu.has_been_loaded.then(function() {
instance.webclient.menu.open_action(state.action);
});
}
}
} else if (state.model && state.id) {
// TODO handle context & domain ?
@@ -152,23 +192,12 @@ instance.web.ActionManager = instance.web.Widget.extend({
action_loaded = this.do_action(action);
} else if (state.sa) {
// load session action
var self = this;
this.null_action();
action_loaded = this.rpc('/web/session/get_session_action', {key: state.sa}).pipe(function(action) {
if (action) {
return self.do_action(action);
}
});
} else if (state.client_action) {
this.null_action();
var action = state.client_action;
if(_.isString(action)) {
action = {
tag: action,
params: state,
};
}
this.ir_actions_client(action);
}
$.when(action_loaded || null).then(function() {
@@ -178,7 +207,10 @@ instance.web.ActionManager = instance.web.Widget.extend({
});
},
do_action: function(action, on_close) {
if (_.isNumber(action) || _.isString(action)) {
if (_.isString(action) && instance.web.client_actions.contains(action)) {
var action_client = { type: "ir.actions.client", tag: action };
return this.do_action(action_client);
} else if (_.isNumber(action) || _.isString(action)) {
var self = this;
return self.rpc("/web/action/load", { action_id: action }, function(result) {
self.do_action(result.result, on_close);
@@ -186,7 +218,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
}
if (!action.type) {
console.error("No type for action", action);
return;
return null;
}
var type = action.type.replace(/\./g,'_');
var popup = action.target === 'new';
@@ -201,7 +233,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
}, action.flags || {});
if (!(type in this)) {
console.error("Action manager can't handle action of type " + action.type, action);
return;
return null;
}
return this[type](action, on_close);
},
@@ -209,6 +241,52 @@ instance.web.ActionManager = instance.web.Widget.extend({
this.dialog_stop();
this.clear_breadcrumbs();
},
do_ir_actions_common: function(action, on_close) {
var self = this, klass, widget, post_process;
if (action.type === 'ir.actions.client') {
var ClientWidget = instance.web.client_actions.get_object(action.tag);
widget = new ClientWidget(this, action.params);
klass = 'oe_act_client';
post_process = function() {
self.push_breadcrumb({
widget: widget,
title: action.name
});
if (action.tag !== 'reload') {
self.do_push_state({});
}
};
} else {
widget = new instance.web.ViewManagerAction(this, action);
klass = 'oe_act_window';
post_process = widget.proxy('add_breadcrumb');
}
if (action.target === 'new') {
if (this.dialog === null) {
// These buttons will be overwrited by <footer> if any
this.dialog = new instance.web.Dialog(this, {
buttons: { "Close": function() { $(this).dialog("close"); }},
dialogClass: klass
});
if(on_close)
this.dialog.on_close.add(on_close);
} else {
this.dialog_widget.destroy();
}
this.dialog.dialog_title = action.name;
this.dialog_widget = widget;
this.dialog_widget.appendTo(this.dialog.$element);
this.dialog.open();
} else {
this.dialog_stop();
this.inner_action = action;
this.inner_widget = widget;
post_process();
this.inner_widget.appendTo(this.$element);
}
},
ir_actions_act_window: function (action, on_close) {
var self = this;
if (_(['base.module.upgrade', 'base.setup.installer'])
@@ -218,34 +296,18 @@ instance.web.ActionManager = instance.web.Widget.extend({
instance.webclient.do_reload().then(old_close);
};
}
if (action.target === 'new') {
if (this.dialog === null) {
// These buttons will be overwrited by <footer> if any
this.dialog = new instance.web.Dialog(this, {
buttons: { "Close": function() { $(this).dialog("close"); }},
dialogClass: 'oe_act_window'
});
if(on_close)
this.dialog.on_close.add(on_close);
} else {
this.dialog_widget.destroy();
}
this.dialog.dialog_title = action.name;
this.dialog_widget = new instance.web.ViewManagerAction(this, action);
this.dialog_widget.appendTo(this.dialog.$element);
this.dialog.open();
} else {
this.dialog_stop();
if (action.target !== 'new') {
if(action.menu_id) {
this.dialog_stop();
return this.getParent().do_action(action, function () {
instance.webclient.menu.open_menu(action.menu_id);
});
}
this.inner_action = action;
var inner_widget = this.inner_widget = new instance.web.ViewManagerAction(this, action);
inner_widget.add_breadcrumb();
this.inner_widget.appendTo(this.$element);
}
return this.do_ir_actions_common(action, on_close);
},
ir_actions_client: function (action, on_close) {
return this.do_ir_actions_common(action, on_close);
},
ir_actions_act_window_close: function (action, on_closed) {
if (!this.dialog && on_closed) {
@@ -262,19 +324,9 @@ instance.web.ActionManager = instance.web.Widget.extend({
self.do_action(action, on_closed)
});
},
ir_actions_client: function (action) {
this.dialog_stop();
var ClientWidget = instance.web.client_actions.get_object(action.tag);
this.inner_widget = new ClientWidget(this, action.params);
this.push_breadcrumb({
widget: this.inner_widget,
title: action.name
});
this.inner_widget.appendTo(this.$element);
},
ir_actions_report_xml: function(action, on_closed) {
var self = this;
$.blockUI();
instance.web.blockUI();
self.rpc("/web/session/eval_domain_and_context", {
contexts: [action.context],
domains: []
@@ -284,7 +336,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
self.session.get_file({
url: '/web/report',
data: {action: JSON.stringify(action)},
complete: $.unblockUI,
complete: instance.web.unblockUI,
success: function(){
if (!self.dialog && on_closed) {
on_closed();
@@ -396,7 +448,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
.find('.oe_view_manager_switch a').filter('[data-view-type="' + view_type + '"]')
.parent().addClass('active');
$.when(view_promise).then(function () {
return $.when(view_promise).then(function () {
_.each(_.keys(self.views), function(view_name) {
var controller = self.views[view_name].controller;
if (controller) {
@@ -408,7 +460,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
container.hide();
controller.do_hide();
}
// put the <footer> in the dialog's buttonpane
// put the <footer> in the dialog's buttonpane
if (self.$element.parent('.ui-dialog-content') && self.$element.find('footer')) {
self.$element.parent('.ui-dialog-content').parent().find('div.ui-dialog-buttonset').hide()
self.$element.find('footer').appendTo(
@@ -418,7 +470,6 @@ instance.web.ViewManager = instance.web.Widget.extend({
}
});
});
return view_promise;
},
do_create_view: function(view_type) {
// Lazy loading of views
@@ -436,6 +487,13 @@ instance.web.ViewManager = instance.web.Widget.extend({
}
var controller = new controllerclass(this, this.dataset, view.view_id, options);
controller.on('history_back', this, function() {
var am = self.getParent();
if (am && am.trigger) {
return am.trigger('history_back');
}
});
controller.on("change:title", this, function() {
if (self.active_view === view_type) {
self.set_title(controller.get('title'));
@@ -478,7 +536,8 @@ instance.web.ViewManager = instance.web.Widget.extend({
});
this.getParent().push_breadcrumb({
widget: this,
show: function(index, $e) {
action: this.action,
show: function(index) {
var view_to_select = views[index];
self.$element.show();
if (self.active_view !== view_to_select) {
@@ -486,9 +545,27 @@ instance.web.ViewManager = instance.web.Widget.extend({
}
},
get_title: function() {
return _.map(views, function(v) {
return self.views[v].controller.get('title');
var id;
var currentIndex;
_.each(self.getParent().breadcrumbs, function(bc, i) {
if (bc.widget === self) {
currentIndex = i;
}
});
var next = self.getParent().breadcrumbs.slice(currentIndex + 1)[0];
var titles = _.map(views, function(v) {
var controller = self.views[v].controller;
if (v === 'form') {
id = controller.datarecord.id;
}
return controller.get('title');
});
if (next && next.action && next.action.res_id && self.active_view === 'form' && self.model === next.action.res_model && id === next.action.res_id) {
// If the current active view is a formview and the next item in the breadcrumbs
// is an action on same object (model / res_id), then we omit the current formview's title
titles.pop();
}
return titles;
}
});
},
@@ -657,32 +734,6 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
this.$element.find('.oe_debug_view').change(this.on_debug_changed);
this.$element.addClass("oe_view_manager_" + (this.action.target || 'current'));
if (this.action.help && !this.flags.low_profile) {
var Users = new instance.web.DataSet(self, 'res.users'),
$tips = this.$element.find('.oe_view_manager_menu_tips');
$tips.delegate('blockquote button', 'click', function() {
var $this = $(this);
//noinspection FallthroughInSwitchStatementJS
switch ($this.attr('name')) {
case 'disable':
Users.write(self.session.uid, {menu_tips:false});
case 'hide':
$this.closest('blockquote').hide();
self.session.hidden_menutips[self.action.id] = true;
}
});
if (!(self.action.id in self.session.hidden_menutips)) {
Users.read_ids([this.session.uid], ['menu_tips']).then(function(users) {
var user = users[0];
if (!(user && user.id === self.session.uid)) {
return;
}
$tips.find('blockquote').toggle(user.menu_tips);
});
}
}
return manager_ready;
},
on_debug_changed: function (evt) {
@@ -736,15 +787,6 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
width: '95%'}, $root).open();
});
break;
case 'manage_views':
if (current_view.fields_view && current_view.fields_view.arch) {
var view_editor = new instance.web.ViewEditor(current_view, current_view.$element, this.dataset, current_view.fields_view.arch);
view_editor.start();
} else {
this.do_warn(_t("Manage Views"),
_t("Could not find current view declaration"));
}
break;
case 'edit_workflow':
return this.do_action({
res_model : 'workflow',
@@ -867,7 +909,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
} else {
self.do_attachement_update(self.dataset, self.model_id);
}
$.unblockUI();
instance.web.unblockUI();
});
},
start: function() {
@@ -1006,7 +1048,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
$e.parent().find('input[type=file]').prop('disabled', true);
$e.parent().find('button').prop('disabled', true).find('img, span').toggle();
this.$('.oe_sidebar_add_attachment span').text(_t('Uploading...'));
$.blockUI();
instance.web.blockUI();
}
},
on_attachment_delete: function(e) {
@@ -1033,14 +1075,15 @@ instance.web.TranslateDialog = instance.web.Dialog.extend({
this['on_button_' + _t("Close")] = this.on_btn_close;
this._super(view, {
width: '80%',
height: '80%'
height: '80%',
destroy_on_close: false,
});
this.view = view;
this.view_type = view.fields_view.type || '';
this.$fields_form = null;
this.$view_form = null;
this.$sidebar_form = null;
this.translatable_fields_keys = _.map(this.view.translatable_fields || [], function(i) { return i.name });
this.translatable_fields_keys = _.map(this.view.translatable_fields || [], function(i) { return i.name; });
this.languages = null;
this.languages_loaded = $.Deferred();
(new instance.web.DataSetSearch(this, 'res.lang', this.view.dataset.get_context(),
@@ -1071,7 +1114,8 @@ instance.web.TranslateDialog = instance.web.Dialog.extend({
deffered.push(deff);
var callback = function(values) {
_.each(self.translatable_fields_keys, function(f) {
self.$fields_form.find('.oe_trad_field[name="' + lg.code + '-' + f + '"]').val(values[0][f] || '').attr('data-value', values[0][f] || '');
var value = values[0][f] || '';
self.$fields_form.find('.oe_trad_field[name="' + lg.code + '-' + f + '"]').val(value).attr('data-value', value);
});
deff.resolve();
};
@@ -1082,24 +1126,19 @@ instance.web.TranslateDialog = instance.web.Dialog.extend({
});
callback([values]);
} else {
self.rpc('/web/dataset/get', {
model: self.view.dataset.model,
ids: [self.view.datarecord.id],
fields: self.translatable_fields_keys,
context: self.view.dataset.get_context({
'lang': lg.code
})}, callback);
self.view.dataset.read_ids([self.view.datarecord.id], self.translatable_fields_keys, {
context: { 'lang': lg.code }
}).then(callback);
}
});
$.when.apply(null, deffered).then(callback);
},
open: function(field) {
var self = this,
sup = this._super;
var self = this;
this._super();
$.when(this.languages_loaded).then(function() {
if (self.view.translatable_fields && self.view.translatable_fields.length) {
self.do_load_fields_values(function() {
sup.call(self);
if (field) {
var $field_input = self.$element.find('tr[data-field="' + field.name + '"] td:nth-child(2) *:first-child');
self.$element.scrollTo($field_input);
@@ -1153,7 +1192,7 @@ instance.web.View = instance.web.Widget.extend({
this.view_id = view_id;
this.set_default_options(options);
},
start: function() {
start: function () {
return this.load_view();
},
load_view: function() {
@@ -1193,7 +1232,7 @@ instance.web.View = instance.web.Widget.extend({
},
open_translate_dialog: function(field) {
if (!this.translate_dialog) {
this.translate_dialog = new instance.web.TranslateDialog(this).start();
this.translate_dialog = new instance.web.TranslateDialog(this);
}
this.translate_dialog.open(field);
},
@@ -1363,7 +1402,6 @@ instance.web.xml_to_json = function(node) {
}
instance.web.json_node_to_xml = function(node, human_readable, indent) {
// For debugging purpose, this function will convert a json node back to xml
// Maybe useful for xml view editor
indent = indent || 0;
var sindent = (human_readable ? (new Array(indent + 1).join('\t')) : ''),
r = sindent + '<' + node.tag,
@@ -1372,7 +1410,9 @@ instance.web.json_node_to_xml = function(node, human_readable, indent) {
if (typeof(node) === 'string') {
return sindent + node;
} else if (typeof(node.tag) !== 'string' || !node.children instanceof Array || !node.attrs instanceof Object) {
throw("Node a json node");
throw new Error(
_.str.sprintf("Node [%s] is not a JSONified XML node",
JSON.stringify(node)));
}
for (var attr in node.attrs) {
var vattr = node.attrs[attr];
+180 -215
View File
@@ -25,6 +25,13 @@
</div>
</div>
</t>
<t t-name="Tipsy.alert">
<a class="oe_tooltip_close oe_e">[</a>
<span style="float:left; margin:2px 5px 0 0;" class="ui-icon ui-icon-alert ui-state-error"></span>
<div class="oe_tooltip_message">
<t t-esc="message"/>
</div>
</t>
<t t-name="CrashManager.warning">
<table cellspacing="0" cellpadding="0" border="0" class="oe_dialog_warning">
@@ -264,6 +271,31 @@
</div>
</t>
<t t-name="ChangePassword">
<form name="change_password_form" method="POST">
<table align="center">
<tr>
<td><label for="old_pwd">Old Password:</label></td>
<td><input type="password" name="old_pwd"
minlength="1" autofocus="autofocus"/></td>
</tr>
<tr>
<td><label for="new_password">New Password:</label></td>
<td><input type="password" name="new_password"
minlength="1" autofocus="autofocus"/></td>
</tr>
<tr>
<td><label for="confirm_pwd">Confirm Password:</label></td>
<td><input type="password" name="confirm_pwd"
minlength="1"/></td>
</tr>
<tr>
<td colspan="2" align="right"><button class="oe_button">Change Password</button></td>
</tr>
</table>
</form>
</t>
<t t-name="Menu">
<ul class="oe_menu" t-if="widget.data">
<li t-foreach="widget.data.data.children" t-as="menu">
@@ -303,7 +335,7 @@
</ul>
</t>
<t t-name="Menu.secondary.link">
<a t-attf-href="#menu_id=#{menu.id}&amp;action_id=#{menu.action ? menu.action.split(',')[1] : ''}"
<a t-attf-href="#menu_id=#{menu.id}&amp;action=#{menu.action ? menu.action.split(',')[1] : ''}"
t-att-class="menu.children.length ? 'oe_menu_toggler' : 'oe_menu_leaf'"
t-att-data-menu="menu.id"
t-att-data-action-model="menu.action ? menu.action.split(',')[0] : ''"
@@ -329,48 +361,24 @@
</span>
</t>
<t t-name="UserMenu.about">
<div>
<a class="oe_activate_debug_mode" href="?debug" style="float:right; font-size: 80%;">Activate the developer mode</a>
<h1 style="margin:0;">OpenERP</h1>
<h3 style="margin:15px 0;padding:0;">Version <t t-esc="version_info.version"/></h3>
<p>
Copyright © 2004-TODAY OpenERP SA. All Rights Reserved.<br />
OpenERP is a trademark of the <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP SA Company</a>.
</p>
<p>
Licenced under the terms of <a target="_blank" href="http://www.gnu.org/licenses/agpl.html" style="text-decoration: underline;">GNU Affero General Public License</a>
</p>
<p>
For more information visit <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP.com</a>
</p>
<div class="oe_about">
<a class="oe_activate_debug_mode oe_right" href="?debug" style="background-color: white; padding:2px 6px; border-radius: 10px;">Activate the developer mode</a>
<img class="oe_logo" src="/web/static/src/img/logo2.png"/>
<h3>Version <t t-esc="version_info.version"/></h3>
<div class="oe_bottom">
<p>Copyright © 2004-TODAY OpenERP SA. All Rights Reserved.<br />
OpenERP is a trademark of the <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP SA Company</a>.</p>
<p>Licenced under the terms of <a target="_blank" href="http://www.gnu.org/licenses/agpl.html" style="text-decoration: underline;">GNU Affero General Public License</a></p>
<p>For more information visit <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP.com</a></p>
</div>
</div>
</t>
<t t-name="UserMenu.password">
<form name="change_password_form" method="POST">
<table align="center">
<tr>
<td><label for="old_pwd">Old Password:</label></td>
<td><input type="password" name="old_pwd"
minlength="1" autofocus="autofocus"/></td>
</tr>
<tr>
<td><label for="new_password">New Password:</label></td>
<td><input type="password" name="new_password"
minlength="1" autofocus="autofocus"/></td>
</tr>
<tr>
<td><label for="confirm_pwd">Confirm Password:</label></td>
<td><input type="password" name="confirm_pwd"
minlength="1"/></td>
</tr>
<tr>
<td colspan="2" align="right"><button class="oe_button">Change Password</button></td>
</tr>
</table>
</form>
</t>
<t t-name="WebClient">
<div class="openerp openerp_webclient_container">
<table class="oe_webclient">
<tr>
<td colspan="2" class="oe_topbar">
@@ -394,15 +402,22 @@
</td>
</tr>
</table>
</div>
</t>
<t t-name="EmbedClient">
<div class="openerp">
<div class="oe_application"></div>
</div>
</t>
<t t-name="ViewManager">
<div class="oe_view_manager">
<table class="oe_view_manager_header">
<col width="20%"/>
<col width="25%"/>
<col width="20%"/>
<col width="35%"/>
<col width="20%"/>
<col width="25%"/>
<col width="20%"/>
<col width="35%"/>
<tr class="oe_header_row oe_header_row_top">
<td colspan="2">
<h2 class="oe_view_title" t-if="widget.flags.display_title !== false">
@@ -511,25 +526,25 @@
<div class="oe_form_dropdown_section">
<button class="oe_dropdown_toggle oe_dropdown_arrow">
<t t-esc="section.label"/>
<ul class="oe_dropdown_menu">
<li t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
<a class="oe_sidebar_action_a" t-att-title="item.title" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url" target="_blank">
<t t-raw="item.label"/>
</a>
<a t-if="section.name == 'files'" class="oe_sidebar_delete_item" t-att-data-id="item.id" title="Delete this attachment">x</a>
</li>
<li t-if="section.name == 'files'" class="oe_sidebar_add_attachment">
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
<t t-set="fileupload_action">/web/binary/upload_attachment</t>
<input type="hidden" name="model" t-att-value="widget.dataset and widget.dataset.model"/>
<input type="hidden" name="id" t-att-value="widget.model_id"/>
<input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
<span>Add...</span>
</t>
</li>
</ul>
</button>
<ul class="oe_dropdown_menu">
<li t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
<a class="oe_sidebar_action_a" t-att-title="item.title" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url" target="_blank">
<t t-raw="item.label"/>
</a>
<a t-if="section.name == 'files'" class="oe_sidebar_delete_item" t-att-data-id="item.id" title="Delete this attachment">x</a>
</li>
<li t-if="section.name == 'files'" class="oe_sidebar_add_attachment">
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
<t t-set="fileupload_action">/web/binary/upload_attachment</t>
<input type="hidden" name="model" t-att-value="widget.dataset and widget.dataset.model"/>
<input type="hidden" name="id" t-att-value="widget.model_id"/>
<input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
<span>Add...</span>
</t>
</li>
</ul>
</div>
</t>
</div>
@@ -600,11 +615,11 @@
</th>
<t t-foreach="columns" t-as="column">
<th t-if="!column.meta and column.invisible !== '1'" t-att-data-id="column.id"
t-att-class="((options.sortable and column.tag !== 'button') ? 'oe_sortable' : null)">
t-attf-class="oe_list_header_#{column.widget or column.type} #{((options.sortable and column.tag !== 'button') ? 'oe_sortable' : null)}">
<t t-if="column.tag !== 'button'"><t t-esc="column.string"/></t>
</th>
</t>
<th t-if="options.deletable" width="1"/>
<th t-if="options.deletable" width="13px"/>
</tr>
</thead>
<tfoot>
@@ -622,9 +637,9 @@
<button type="button" class="oe_button oe_list_add oe_highlight">
<t t-esc="widget.options.addable"/>
</button>
<t t-if="widget.options.import_enabled">
<span class="oe_alternative" t-if="widget.options.import_enabled">
<span class="oe_fade">or</span> <a href="#" class="oe_bold oe_list_button_import">Import</a>
</t>
</span>
</t>
</div>
<t t-name="ListView.pager">
@@ -638,16 +653,14 @@
<t t-name="ListView.rows" t-foreach="records.length" t-as="index">
<t t-call="ListView.row">
<t t-set="record" t-value="records.at(index)"/>
<t t-set="row_parity" t-value="index_parity"/>
</t>
</t>
<tr t-name="ListView.row" t-att-class="row_parity"
<tr t-name="ListView.row"
t-att-data-id="record.get('id')"
t-att-style="view.style_for(record)">
<t t-set="asData" t-value="record.toForm().data"/>
<t t-foreach="columns" t-as="column">
<td t-if="column.meta">
</td>
<td t-if="column.meta"> </td>
</t>
<th t-if="options.selectable" class="oe_list_record_selector" width="1">
<t t-set="checked" t-value="options.select_view_id == record.get('id') ? 'checked' : null"/>
@@ -655,23 +668,34 @@
<input t-if="!options.radio" type="checkbox" name="radiogroup" t-att-checked="checked"/>
</th>
<t t-foreach="columns" t-as="column">
<t t-set="align" t-value="column.type === 'integer' or column.type == 'float'"/>
<t t-set="number" t-value="column.type === 'integer' or column.type == 'float'"/>
<t t-set="modifiers" t-value="column.modifiers_for(asData)"/>
<td t-if="!column.meta and column.invisible !== '1'" t-att-title="column.help"
t-att-class="'oe_list_field_cell' + (align ? ' oe_number' : '')
+ (column.tag === 'button' ? ' oe_button' : '')"
t-att-data-field="column.id">
<t t-raw="render_cell(record, column)"/>
</td>
t-attf-class="oe_list_field_cell oe_list_field_#{column.widget or column.type} #{number ? 'oe_number' : ''} #{column.tag === 'button' ? 'oe-button' : ''} #{modifiers.readonly ? 'oe_readonly' : ''} #{modifiers.required ? 'oe_required' : ''}"
t-att-data-field="column.id"
><t t-raw="render_cell(record, column)"/></td>
</t>
<td t-if="options.deletable" class='oe_list_record_delete' width="1">
<td t-if="options.deletable" class='oe_list_record_delete' width="13px">
<button type="button" name="delete" class="oe_i">d</button>
</td>
</tr>
<t t-name="ListView.row.save">
<td>
<button class='oe_i oe_list_edit_row_save' type='button' name='save'/>
</td>
<t t-extend="ListView.buttons">
<t t-jquery="button.oe_list_add" t-operation="after">
<button class="oe_button oe_list_save oe_highlight"
type="button">Save</button>
</t>
<t t-jquery="a.oe_list_button_import" t-operation="after">
<a href="#" class="oe_bold oe_list_discard">discard</a>
</t>
</t>
<t t-extend="ListView.row">
<!-- adds back padding to row being rendered after edition, if necessary
(if not deletable add back padding), otherwise the row being added is
missing columns
-->
<t t-jquery="&gt; :last" t-operation="after">
<td t-if="edited and !options.deletable" class="oe-listview-padding"/>
</t>
</t>
<t t-name="FormView">
@@ -685,7 +709,9 @@
<div t-name="FormView.buttons" class="oe_form_buttons">
<t t-if="widget.options.action_buttons !== false">
<span class="oe_form_buttons_view">
<button type="button" class="oe_button oe_form_button_edit">Edit</button>
<div style="display: inline-block;"> <!-- required for the bounce effect on button -->
<button type="button" class="oe_button oe_form_button_edit">Edit</button>
</div>
<button type="button" class="oe_button oe_form_button_create">Create</button>
</span>
<span class="oe_form_buttons_edit">
@@ -772,7 +798,7 @@
<table border="0" cellpadding="0" cellspacing="0" t-attf-class="oe_form_group #{classnames}"/>
</t>
<t t-name="FormRenderingNotebook">
<div>
<div class="oe_clear">
<ul t-attf-class="oe_notebook #{classnames}">
<li t-foreach="pages" t-as="page" t-att-modifiers="page.modifiers">
<a t-attf-href="##{page.id}">
@@ -787,7 +813,7 @@
</div>
</t>
<t t-name="FormRenderingSeparator">
<div t-attf-class="oe_horizontal_separator #{classnames}">
<div t-attf-class="oe_horizontal_separator oe_clear #{classnames}">
<t t-esc="string"/>
</div>
</t>
@@ -905,9 +931,10 @@
t-att-tabindex="widget.node.attrs.tabindex"
t-att-autofocus="widget.node.attrs.autofocus"
t-att-placeholder="! widget.get('effective_readonly') ? widget.node.attrs.placeholder : ''"
></textarea>
<img class="oe_field_translate oe_input_icon" t-if="widget.field.translate"
t-att-src='_s + "/web/static/src/img/icons/terp-translate.png"' width="16" height="16" border="0"/>
></textarea><img class="oe_field_translate oe_input_icon"
t-if="widget.field.translate and !widget.get('effective_readonly')"
t-att-src='_s + "/web/static/src/img/icons/terp-translate.png"' width="16" height="16" border="0"
/>
</div>
</t>
<t t-name="web.datepicker">
@@ -943,11 +970,14 @@
</t>
<t t-name="FieldMany2One">
<span class="oe_form_field oe_form_field_many2one oe_form_field_with_button" t-att-style="widget.node.attrs.style">
<a t-if="widget.get('effective_readonly')" href="#" class="oe_form_uri"/>
<t t-if="widget.get('effective_readonly')">
<a t-if="! widget.get_definition_options().no_open" href="#" class="oe_form_uri"/>
<span t-if="widget.get_definition_options().no_open" href="#" class="oe_form_uri"/>
<span class="oe_form_m2o_follow"/>
</t>
<t t-if="!widget.get('effective_readonly')">
<button class="oe_button oe_m2o_cm_button" title="Open Resource">
<img t-att-src='_s + "/web/static/src/img/icons/terp-folder-yellow.png"'/>
</button>
<a t-if="! widget.get_definition_options().no_open" href="#" tabindex="-1"
class="oe_m2o_cm_button oe_e">/</a>
<div>
<input type="text"
t-att-id="widget.id_for_label"
@@ -962,7 +992,6 @@
</t>
</span>
</t>
<!-- Collection of m2m tags -->
<t t-name="FieldMany2ManyTags">
<div class="oe_form_field oe_tags" t-att-style="widget.node.attrs.style">
<t t-if="! widget.get('effective_readonly')">
@@ -971,7 +1000,6 @@
</t>
</div>
</t>
<!-- Individual m2m tag element -->
<t t-name="FieldMany2ManyTag">
<t t-set="i" t-value="0"/>
<t t-foreach="elements" t-as="el">
@@ -1009,14 +1037,19 @@
</span>
</t>
<t t-name="FieldStatus">
<ul class="oe_form_steps" t-att-style="widget.node.attrs.style"/>
<ul class="" t-att-style="widget.node.attrs.style"/>
</t>
<t t-name="FieldStatus.content">
<t t-set="size" t-value="widget.to_show.length"/>
<t t-foreach="_.range(size)" t-as="i">
<li t-att-class="widget.to_show[i][0] === widget.selected_value ? 'oe_form_steps_active' : ''">
<span><t t-esc="widget.to_show[i][1]"/></span>
<img t-att-src='_s + "/web/static/src/img/form_steps.png"' class="oe_form_steps_arrow" t-if="i &lt; size - 1"/>
<li t-att-class="widget.to_show[i][0] === widget.selected_value ? 'oe_form_steps_active' : 'oe_form_steps_inactive'">
<div class="oe_form_steps_button" t-att-data-id="widget.to_show[i][0]">
<t t-esc="widget.to_show[i][1]"/>
<span class="oe_form_steps_arrow">
<span></span>
</span>
<img t-att-src='_s + "/web/static/src/img/form_steps.png"' class="oe_form_steps_arrow" t-if="i &lt; size - 1"/>
</div>
</li>
</t>
</t>
@@ -1119,7 +1152,7 @@
t-att-style="widget.node.attrs.style"
t-att-tabindex="widget.node.attrs.tabindex"
t-att-autofocus="widget.node.attrs.autofocus">
<img t-if="widget.node.attrs.icon" t-att-src="_s + '/web/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/>
<img t-if="widget.node.attrs.icon" t-att-src="_s + widget.node.attrs.icon" width="16" height="16"/>
<span t-if="widget.string"><t t-esc="widget.string"/></span>
</button>
</t>
@@ -1167,16 +1200,51 @@
</tr>
<tr t-foreach="widget.view.translatable_fields" t-as="field" t-att-data-field="field.name">
<td class="oe_form_group_cell" width="1%" nowrap="nowrap">
<label class="oe_label"><t t-esc="field.node.attrs.string"/>:</label>
<label class="oe_label"><t t-esc="field.string"/>:</label>
</td>
<td t-foreach="widget.languages" t-as="lg" class="oe_form_group_cell">
<input t-if="field.type == 'char'" type="text" t-attf-name="#{lg.code}-#{field.name}" value="" data-value="" class="oe_trad_field" style="width: 100%"/>
<textarea t-if="field.type == 'text'" t-attf-name="#{lg.code}-#{field.name}" data-value="" class="oe_trad_field" style="width: 100%"></textarea>
<input t-if="field.field.type == 'char'" type="text" t-attf-name="#{lg.code}-#{field.name}" value="" data-value="" class="oe_trad_field" style="width: 100%"/>
<textarea t-if="field.field.type == 'text'" t-attf-name="#{lg.code}-#{field.name}" data-value="" class="oe_trad_field" style="width: 100%"></textarea>
</td>
</tr>
</table>
</t>
<t t-name="AbstractFormPopup.render">
<div>
<table style="width:100%">
<tr style="width:100%">
<td style="width:100%">
<div class="oe_popup_search" style="width:100%"></div>
</td>
</tr>
<tr style="width:100%">
<td style="width:100%">
<div class="oe_popup_list" style="width:100%"></div>
</td>
</tr>
</table>
<div class="oe_popup_form" style="width:100%"></div>
</div>
</t>
<t t-name="SelectCreatePopup.search.buttons">
<t t-if="! widget.options.disable_multiple_selection">
<button type="button" class="oe_button oe_selectcreatepopup-search-select" disabled="disabled">Select</button>
or
</t>
<a class="oe_button oe_selectcreatepopup-search-close oe_bold oe_form_button_cancel" href="javascript:void(0)">Cancel</a>
</t>
<t t-name="AbstractFormPopup.buttons">
<t t-if="! multi_select">
<button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save</button>
</t>
<t t-if="multi_select">
<button type="button" class="oe_button oe_abstractformpopup-form-save-new oe_highlight">Save &amp; New</button>
<button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save &amp; Close</button>
</t>
or <a class="oe_button oe_abstractformpopup-form-close oe_bold oe_form_button_cancel" href="javascript:void(0)">Discard</a>
</t>
<t t-name="One2Many.viewmanager" t-extend="ViewManager">
<t t-jquery=".oe-view-manager-header">
this.attr('t-if', 'views.length != 1');
@@ -1207,6 +1275,8 @@
<div class="oe_searchview_clear"/>
<div class="oe_searchview_unfold_drawer" title="Advanced Search..."/>
<div class="oe_searchview_drawer"/>
<button type="button" class="oe_searchview_search"
title="Search Again">Search</button>
</div>
<div t-name="SearchView.InputView"
@@ -1227,7 +1297,6 @@
<span t-name="SearchView.FacetView.Value" class="oe_facet_value">
<t t-esc="widget.model.get('label')"/>
</span>
<t t-name="SearchView.managed-filters">
<option class="oe_search_filters_title" value="">Filters</option>
<optgroup label="-- Filters --">
@@ -1252,7 +1321,6 @@
<p>(Any existing filter with the same name will be replaced)</p>
</div>
</t>
<t t-name="SearchView.render_lines">
<table class="oe_search_render_line" border="0" cellspacing="0" cellpadding="0"
t-foreach="lines" t-as="line">
@@ -1391,18 +1459,18 @@
<div>
</div>
</div>
<div t-name="SearchView.addtodashboard" class="oe_searchview_dashboard">
<div t-name="SearchView.addtoreporting" class="oe_searchview_dashboard">
<h4>Add to Dashboard</h4>
<form>
<input placeholder ="Title of new Dashboard item" title = "Title of new Dashboard item" type="text"/>
<button class="oe_apply" type="submit">save</button>
<p><input placeholder="Title of new dashboard item"/></p>
<button class="oe_apply" type="submit">Add</button>
</form>
</div>
<t t-name="SearchView.addtodashboard.selection">
<select title = "Select Dashboard to add this filter to">
<t t-foreach="selections" t-as="element">
<option t-att-value="element.id || element.res_id "><t t-esc="element.name"/></option>
</t>
<t t-name="SearchView.addtoreporting.selection">
<select>
<option t-foreach="selections" t-as="element"
t-att-value="element.id || element.res_id ">
<t t-esc="element.name"/></option>
</select>
</t>
<div t-name="SearchView.advanced" class="oe_searchview_advanced">
@@ -1449,110 +1517,7 @@
</t>
</select>
</t>
<t t-name="AbstractFormPopup.render">
<div>
<table style="width:100%">
<tr style="width:100%">
<td style="width:100%">
<div class="oe_popup_search" style="width:100%"></div>
</td>
</tr>
<tr style="width:100%">
<td style="width:100%">
<div class="oe_popup_list" style="width:100%"></div>
</td>
</tr>
</table>
<div class="oe_popup_form" style="width:100%"></div>
</div>
</t>
<t t-name="SelectCreatePopup.search.buttons">
<button type="button" class="oe_button oe_selectcreatepopup-search-select" disabled="disabled">Select</button>
<button type="button" class="oe_button oe_selectcreatepopup-search-close">Cancel</button>
</t>
<t t-name="AbstractFormPopup.buttons">
<t t-if="! multi_select">
<button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save</button>
</t>
<t t-if="multi_select">
<button type="button" class="oe_button oe_abstractformpopup-form-save-new oe_highlight">Save &amp; New</button>
<button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save &amp; Close</button>
</t>
<button type="button" class="oe_button oe_abstractformpopup-form-close">Cancel</button>
</t>
<t t-extend="ListView.row">
<!-- adds back padding to row being rendered after edition, if necessary
(if not deletable add back padding), otherwise the row being added is
missing columns
-->
<t t-jquery="&gt; :last" t-operation="after">
<td t-if="edited and !options.deletable" class="oe_list_padding"/>
</t>
</t>
<t t-name="view_editor">
<table class="oe_view_editor">
<t t-call="view_editor.row"/>
</table>
</t>
<t t-name="view_editor.row">
<tr t-att-id="'viewedit-' + rec.id" t-att-level="rec.level" t-foreach="data" t-as="rec">
<td width="90%">
<table class="oe_view_editor_field">
<tr>
<td width="16px" t-att-style="'background-position: ' + 20*rec.level + 'px; padding-left: ' + 20*rec.level + 'px'">
<img t-if="rec.child_id.length" t-att-id="'parentimg-' + rec.id"
t-att-src='_s + "/web/static/src/img/collapse.gif"' width="16" height="16" border="0"/>
</td>
<td style="cursor: pointer;">
<a style="text-decoration:none" href="javascript:void(0);">
<t t-esc="rec.name"/>
</a>
</td>
</tr>
</table>
</td>
<td width="2%">
<img t-if="rec.att_list.length"
id="side-add" t-att-src='_s + "/web/static/src/img/icons/gtk-add.png"' style="cursor: pointer;"/>
</td>
<td width="2%">
<img id="side-remove" t-att-src='_s + "/web/static/src/img/icons/gtk-remove.png"' style="cursor: pointer;"/>
</td>
<td width="2%">
<img t-if="rec.att_list.length and !_.include(no_properties, rec.att_list[0])"
id="side-edit" t-att-src='_s + "/web/static/src/img/icons/gtk-edit.png"' style="cursor: pointer;"/>
</td>
<td width="2%">
<img t-if="rec.att_list.length"
id="side-up" t-att-src='_s + "/web/static/src/img/icons/gtk-go-up.png"' style="cursor: pointer;"/>
</td>
<td width="2%">
<img t-if="rec.att_list.length"
id="side-down" t-att-src='_s + "/web/static/src/img/icons/gtk-go-down.png"' style="cursor: pointer;"/>
</td>
<t t-if="rec.child_id.length">
<t t-set="data" t-value="rec.child_id"/>
<t t-call="view_editor.row"/>
</t>
</tr>
</t>
<t t-name="vieweditor_char">
<input type="text" t-att-id="widget.name" class="field_char" size="50"/>
</t>
<t t-name="vieweditor_selection">
<select t-att-id="widget.name" >
<t t-if="widget.selection" t-foreach="widget.selection" t-as="option">
<option
t-att-value="typeof option === 'object' ? option[0] : option">
<t t-esc="typeof option === 'object' ? option[1] : option"/>
</option>
</t>
</select>
</t>
<t t-name="vieweditor_boolean">
<input type="checkbox" t-att-id="widget.name"/>
</t>
<t t-name="ExportView">
<a id="exportview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Export</a>
</t>
+239
View File
@@ -0,0 +1,239 @@
$(document).ready(function () {
var $fix = $('#qunit-fixture');
var mod = {
setup: function () {
instance = window.openerp.init([]);
window.openerp.web.corelib(instance);
instance.web.qweb = new QWeb2.Engine();
instance.web.qweb.add_template(
'<no>' +
'<t t-name="test.widget.template">' +
'<ol>' +
'<li t-foreach="5" t-as="counter" ' +
't-attf-class="class-#{counter}">' +
'<input/>' +
'<t t-esc="counter"/>' +
'</li>' +
'</ol>' +
'</t>' +
'<t t-name="test.widget.template-value">' +
'<p><t t-esc="widget.value"/></p>' +
'</t>' +
'</no>');
}
};
var instance;
module('Widget.proxy', mod);
test('(String)', function () {
var W = instance.web.Widget.extend({
exec: function () {
this.executed = true;
}
});
var w = new W;
var fn = w.proxy('exec');
fn();
ok(w.executed, 'should execute the named method in the right context');
});
test('(String)(*args)', function () {
var W = instance.web.Widget.extend({
exec: function (arg) {
this.executed = arg;
}
});
var w = new W;
var fn = w.proxy('exec');
fn(42);
ok(w.executed, "should execute the named method in the right context");
equal(w.executed, 42, "should be passed the proxy's arguments");
});
test('(String), include', function () {
// the proxy function should handle methods being changed on the class
// and should always proxy "by name", to the most recent one
var W = instance.web.Widget.extend({
exec: function () {
this.executed = 1;
}
});
var w = new W;
var fn = w.proxy('exec');
W.include({
exec: function () { this.executed = 2; }
});
fn();
equal(w.executed, 2, "should be lazily resolved");
});
test('(Function)', function () {
var w = new (instance.web.Widget.extend({ }));
var fn = w.proxy(function () { this.executed = true; });
fn();
ok(w.executed, "should set the function's context (like Function#bind)");
});
test('(Function)(*args)', function () {
var w = new (instance.web.Widget.extend({ }));
var fn = w.proxy(function (arg) { this.executed = arg; });
fn(42);
equal(w.executed, 42, "should be passed the proxy's arguments");
});
module('Widget.renderElement', mod);
test('no template, default', function () {
var w = new (instance.web.Widget.extend({ }));
var $original = w.$element;
ok($original, "should initially have a root element");
w.renderElement();
ok(w.$element, "should have generated a root element");
ok($original !== w.$element, "should have generated a new root element");
strictEqual(w.$element, w.$element, "should provide $element alias");
ok(w.$element.is(w.el), "should provide raw DOM alias");
equal(w.el.nodeName, 'DIV', "should have generated the default element");
equal(w.el.attributes.length, 0, "should not have generated any attribute");
ok(_.isEmpty(w.$element.html(), "should not have generated any content"));
});
test('no template, custom tag', function () {
var w = new (instance.web.Widget.extend({
tagName: 'ul'
}));
w.renderElement();
equal(w.el.nodeName, 'UL', "should have generated the custom element tag");
});
test('no template, @id', function () {
var w = new (instance.web.Widget.extend({
id: 'foo'
}));
w.renderElement();
equal(w.el.attributes.length, 1, "should have one attribute");
equal(w.$element.attr('id'), 'foo', "should have generated the id attribute");
equal(w.el.id, 'foo', "should also be available via property");
});
test('no template, @className', function () {
var w = new (instance.web.Widget.extend({
className: 'oe_some_class'
}));
w.renderElement();
equal(w.el.className, 'oe_some_class', "should have the right property");
equal(w.$element.attr('class'), 'oe_some_class', "should have the right attribute");
});
test('no template, bunch of attributes', function () {
var w = new (instance.web.Widget.extend({
attributes: {
'id': 'some_id',
'class': 'some_class',
'data-foo': 'data attribute',
'clark': 'gable',
'spoiler': 'snape kills dumbledore'
}
}));
w.renderElement();
equal(w.el.attributes.length, 5, "should have all the specified attributes");
equal(w.el.id, 'some_id');
equal(w.$element.attr('id'), 'some_id');
equal(w.el.className, 'some_class');
equal(w.$element.attr('class'), 'some_class');
equal(w.$element.attr('data-foo'), 'data attribute');
equal(w.$element.data('foo'), 'data attribute');
equal(w.$element.attr('clark'), 'gable');
equal(w.$element.attr('spoiler'), 'snape kills dumbledore');
});
test('template', function () {
var w = new (instance.web.Widget.extend({
template: 'test.widget.template'
}));
w.renderElement();
equal(w.el.nodeName, 'OL');
equal(w.$element.children().length, 5);
equal(w.el.textContent, '01234');
});
module('Widget.$', mod);
test('basic-alias', function () {
var w = new (instance.web.Widget.extend({
template: 'test.widget.template'
}));
w.renderElement();
ok(w.$('li:eq(3)').is(w.$element.find('li:eq(3)')),
"should do the same thing as calling find on the widget root");
});
module('Widget.events', mod);
test('delegate', function () {
var a = [];
var w = new (instance.web.Widget.extend({
template: 'test.widget.template',
events: {
'click': function () {
a[0] = true;
strictEqual(this, w, "should trigger events in widget")
},
'click li.class-3': 'class3',
'change input': function () { a[2] = true; }
},
class3: function () { a[1] = true; }
}));
w.renderElement();
w.$element.click();
w.$('li:eq(3)').click();
w.$('input:last').val('foo').change();
for(var i=0; i<3; ++i) {
ok(a[i], "should pass test " + i);
}
});
test('undelegate', function () {
var clicked = false, newclicked = false;
var w = new (instance.web.Widget.extend({
template: 'test.widget.template',
events: { 'click li': function () { clicked = true; } }
}));
w.renderElement();
w.$element.on('click', 'li', function () { newclicked = true });
w.$('li').click();
ok(clicked, "should trigger bound events");
ok(newclicked, "should trigger bound events");
clicked = newclicked = false;
w.undelegateEvents();
w.$('li').click();
ok(!clicked, "undelegate should unbind events delegated");
ok(newclicked, "undelegate should only unbind events it created");
});
module('Widget.renderElement', mod);
test('repeated', function () {
var w = new (instance.web.Widget.extend({
template: 'test.widget.template-value'
}));
w.value = 42;
w.appendTo($fix)
.always(start)
.done(function () {
equal($fix.find('p').text(), '42', "DOM fixture should contain initial value");
equal(w.$element.text(), '42', "should set initial value");
w.value = 36;
w.renderElement();
equal($fix.find('p').text(), '36', "DOM fixture should use new value");
equal(w.$element.text(), '36', "should set new value");
});
});
});
+16
View File
@@ -133,4 +133,20 @@ $(document).ready(function () {
}]);
deepEqual(result, {type: 'out_invoice'});
});
module('eval.domains', {
setup: function () {
openerp = window.openerp.testing.instanceFor('coresetup');
window.openerp.web.dates(openerp);
}
});
test('current_date', function () {
var current_date = openerp.web.date_to_str(new Date());
var result = openerp.connection.test_eval_domains(
[[],{"__ref":"domain","__debug":"[('name','>=',current_date),('name','<=',current_date)]","__id":"5dedcfc96648"}],
openerp.connection.test_eval_get_context());
deepEqual(result, [
['name', '>=', current_date],
['name', '<=', current_date]
]);
})
});
+349
View File
@@ -0,0 +1,349 @@
$(document).ready(function () {
var $fix = $('#qunit-fixture');
var instance;
var baseSetup = function () {
instance = openerp.testing.instanceFor('list_editable');
openerp.testing.loadTemplate(instance);
openerp.testing.mockifyRPC(instance);
};
/**
*
* @param {String} name
* @param {Object} [attrs]
* @param {String} [attrs.type="char"]
* @param {Boolean} [attrs.required]
* @param {Boolean} [attrs.invisible]
* @param {Boolean} [attrs.readonly]
* @return {Object}
*/
function field(name, attrs) {
attrs = attrs || {};
attrs.name = name;
return _.defaults(attrs, {
type: 'char'
});
}
/**
* @param {Array} fields
* @return {Object}
*/
function makeFormView(fields) {
var fobj = {};
_(fields).each(function (field) {
fobj[field.name] = {
type: field.type,
string: field.string
};
});
var children = _(fields).map(function (field) {
return {
tag: 'field',
attrs: {
name: field.name,
modifiers: JSON.stringify({
required: field.required,
invisible: field.invisible,
readonly: field.readonly
})
}
}
});
return {
arch: {
tag: 'form',
attrs: {
version: '7.0',
'class': 'oe_form_container'
},
children: children
},
fields: fobj
};
}
module('editor', {
setup: baseSetup
});
asyncTest('base-state', 2, function () {
var e = new instance.web.list.Editor({
dataset: {ids: []},
edition_view: function () {
return makeFormView();
}
});
e.appendTo($fix)
.always(start)
.fail(function (error) { ok(false, error && error.message); })
.done(function () {
ok(!e.is_editing(), "should not be editing");
ok(e.form instanceof instance.web.FormView,
"should use default form type");
});
});
asyncTest('toggle-edition-save', 4, function () {
instance.connection.responses['/web/dataset/call_kw:create'] = function () {
return { result: 42 };
};
instance.connection.responses['/web/dataset/call_kw:read'] = function () {
return { result: [{
id: 42,
a: false,
b: false,
c: false
}]};
};
var e = new instance.web.list.Editor({
dataset: new instance.web.DataSetSearch(),
prepends_on_create: function () { return false; },
edition_view: function () {
return makeFormView([ field('a'), field('b'), field('c') ]);
}
});
var counter = 0;
e.appendTo($fix)
.pipe(function () {
return e.edit({}, function () {
++counter;
});
})
.pipe(function (form) {
ok(e.is_editing(), "should be editing");
equal(counter, 3, "should have configured all fields");
return e.save();
})
.always(start)
.fail(function (error) { ok(false, error && error.message); })
.done(function (record) {
ok(!e.is_editing(), "should have stopped editing");
equal(record.id, 42, "should have newly created id");
})
});
asyncTest('toggle-edition-cancel', 2, function () {
instance.connection.responses['/web/dataset/call_kw:create'] = function () {
return { result: 42 };
};
var e = new instance.web.list.Editor({
dataset: new instance.web.DataSetSearch(),
prepends_on_create: function () { return false; },
edition_view: function () {
return makeFormView([ field('a'), field('b'), field('c') ]);
}
});
var counter = 0;
e.appendTo($fix)
.pipe(function () {
return e.edit({}, function () {
++counter;
});
})
.pipe(function (form) {
return e.cancel();
})
.always(start)
.fail(function (error) { ok(false, error && error.message); })
.done(function (record) {
ok(!e.is_editing(), "should have stopped editing");
ok(!record.id, "should have no id");
})
});
asyncTest('toggle-save-required', 2, function () {
instance.connection.responses['/web/dataset/call_kw:create'] = function () {
return { result: 42 };
};
var e = new instance.web.list.Editor({
do_warn: function () {
warnings++;
},
dataset: new instance.web.DataSetSearch(),
prepends_on_create: function () { return false; },
edition_view: function () {
return makeFormView([
field('a', {required: true}), field('b'), field('c') ]);
}
});
var counter = 0;
var warnings = 0;
e.appendTo($fix)
.pipe(function () {
return e.edit({}, function () {
++counter;
});
})
.pipe(function (form) {
return e.save();
})
.always(start)
.done(function () { ok(false, "cancel should not succeed"); })
.fail(function () {
equal(warnings, 1, "should have been warned");
ok(e.is_editing(), "should have kept editing");
})
});
module('list-edition', {
setup: function () {
baseSetup();
var records = {};
_.extend(instance.connection.responses, {
'/web/listview/load': function () {
return {result: {
type: 'tree',
fields: {
a: {type: 'char', string: "A"},
b: {type: 'char', string: "B"},
c: {type: 'char', string: "C"}
},
arch: {
tag: 'tree',
attrs: {},
children: [
{tag: 'field', attrs: {name: 'a'}},
{tag: 'field', attrs: {name: 'b'}},
{tag: 'field', attrs: {name: 'c'}}
]
}
}};
},
'/web/dataset/call_kw:create': function (params) {
records[42] = _.extend({}, params.params.args[0]);
return {result: 42};
},
'/web/dataset/call_kw:read': function (params) {
var id = params.params.args[0][0];
if (id in records) {
return {result: [records[id]]};
}
return {result: []};
}
})
}
});
asyncTest('newrecord', 6, function () {
var got_defaults = false;
instance.connection.responses['/web/dataset/call_kw:default_get'] = function (params) {
var fields = params.params.args[0];
deepEqual(
fields, ['a', 'b', 'c'],
"should ask defaults for all fields");
got_defaults = true;
return {result: {
a: "qux",
b: "quux"
}};
};
var ds = new instance.web.DataSetStatic(null, 'demo', null, [1]);
var l = new instance.web.ListView({}, ds, false, {editable: 'top'});
l.appendTo($fix)
.pipe(l.proxy('reload_content'))
.pipe(function () {
return l.start_edition();
})
.always(start)
.pipe(function () {
ok(got_defaults, "should have fetched default values for form");
return l.save_edition();
})
.pipe(function (result) {
ok(result.created, "should yield newly created record");
equal(result.record.get('a'), "qux",
"should have used default values");
equal(result.record.get('b'), "quux",
"should have used default values");
ok(!result.record.get('c'),
"should have no value if there was no default");
})
.fail(function (e) { ok(false, e && e.message || e); });
});
module('list-edition-events', {
setup: function () {
baseSetup();
_.extend(instance.connection.responses, {
'/web/listview/load': function () {
return {result: {
type: 'tree',
fields: {
a: {type: 'char', string: "A"},
b: {type: 'char', string: "B"},
c: {type: 'char', string: "C"}
},
arch: {
tag: 'tree',
attrs: {},
children: [
{tag: 'field', attrs: {name: 'a'}},
{tag: 'field', attrs: {name: 'b'}},
{tag: 'field', attrs: {name: 'c'}}
]
}
}};
},
'/web/dataset/call_kw:read': function (params) {
return {result: [{
id: 1,
a: 'foo',
b: 'bar',
c: 'baz'
}]};
}
});
}
});
asyncTest('edition events', 4, function () {
var ds = new instance.web.DataSetStatic(null, 'demo', null, [1]);
var o = {
counter: 0,
onEvent: function (e) { this.counter++; }
};
var l = new instance.web.ListView({}, ds, false, {editable: 'top'});
l.on('edit:before edit:after', o, o.onEvent);
l.appendTo($fix)
.pipe(l.proxy('reload_content'))
.always(start)
.pipe(function () {
ok(l.options.editable, "should be editable");
equal(o.counter, 0, "should have seen no event yet");
return l.start_edition(l.records.get(1));
})
.pipe(function () {
ok(l.editor.is_editing(), "should be editing");
equal(o.counter, 2, "should have seen two edition events");
})
.fail(function (e) { ok(false, e && e.message); });
});
asyncTest('edition events: cancelling', 3, function () {
var edit_after = false;
var ds = new instance.web.DataSetStatic(null, 'demo', null, [1]);
var l = new instance.web.ListView({}, ds, false, {editable: 'top'});
l.on('edit:before', {}, function (e) {
e.cancel = true;
});
l.on('edit:after', {}, function () {
edit_after = true;
});
l.appendTo($fix)
.pipe(l.proxy('reload_content'))
.always(start)
.pipe(function () {
ok(l.options.editable, "should be editable");
return l.start_edition();
})
// cancelling an event rejects the deferred
.pipe($.Deferred().reject(), function () {
ok(!l.editor.is_editing(), "should not be editing");
ok(!edit_after, "should not have fired the edit:after event");
return $.when();
})
.fail(function (e) { ok(false, e && e.message || e); });
});
});
+113 -8
View File
@@ -133,7 +133,7 @@ $(document).ready(function () {
strictEqual(changed, 1);
});
module('list-collections-degenerate', {
module('list-collections', {
setup: function () {
openerp = window.openerp.init([]);
window.openerp.web.corelib(openerp);
@@ -145,7 +145,7 @@ $(document).ready(function () {
window.openerp.web.list(openerp);
}
});
test('Fetch from collection', function () {
test('degenerate-fetch', function () {
var c = new openerp.web.list.Collection();
strictEqual(c.length, 0);
c.add({id: 1, value: 2});
@@ -163,7 +163,7 @@ $(document).ready(function () {
strictEqual(r2.get('id'), 1);
strictEqual(r2.get('value'), 2);
});
test('Add at index', function () {
test('degenerate-indexed-add', function () {
var c = new openerp.web.list.Collection([
{id: 1, value: 5},
{id: 2, value: 10},
@@ -175,7 +175,7 @@ $(document).ready(function () {
strictEqual(c.at(1).get('value'), 55);
strictEqual(c.at(3).get('value'), 20);
});
test('Remove record', function () {
test('degenerate-remove', function () {
var c = new openerp.web.list.Collection([
{id: 1, value: 5},
{id: 2, value: 10},
@@ -188,7 +188,7 @@ $(document).ready(function () {
equal(c.get(2), undefined);
strictEqual(c.at(1).get('value'), 20);
});
test('Remove unbind', function () {
test('degenerate-remove-bound', function () {
var changed = false,
c = new openerp.web.list.Collection([ {id: 1, value: 5} ]);
c.bind('change', function () { changed = true; });
@@ -198,7 +198,7 @@ $(document).ready(function () {
ok(!changed, 'removed records should not trigger events in their ' +
'parent collection');
});
test('Reset', function () {
test('degenerate-reset', function () {
var event, obj, c = new openerp.web.list.Collection([
{id: 1, value: 5},
{id: 2, value: 10},
@@ -218,7 +218,7 @@ $(document).ready(function () {
strictEqual(c.length, 1);
strictEqual(c.get(42).get('value'), 55);
});
test('Reset unbind', function () {
test('degenerate-reset-bound', function () {
var changed = false,
c = new openerp.web.list.Collection([ {id: 1, value: 5} ]);
c.bind('change', function () { changed = true; });
@@ -229,7 +229,7 @@ $(document).ready(function () {
'parent collection');
});
test('Events propagation', function () {
test('degenerate-propagations', function () {
var values = [];
var c = new openerp.web.list.Collection([
{id: 1, value: 5},
@@ -260,6 +260,82 @@ $(document).ready(function () {
c.at(1).set('wealth', 5);
strictEqual(total, 47);
});
test('degenerate-successor', function () {
var root = new openerp.web.list.Collection([
{id: 1, value: 1},
{id: 2, value: 2},
{id: 3, value: 3},
{id: 4, value: 5},
{id: 5, value: 8}
]);
deepEqual(root.succ(root.at(2)).attributes,
root.at(3).attributes,
"should return the record at (index + 1) from the pivot");
equal(root.succ(root.at(4)), null,
"should return null as successor to last record");
deepEqual(root.succ(root.at(4), {wraparound: true}).attributes,
root.at(0).attributes,
"should return index 0 as successor to last record if" +
" wraparound is set");
deepEqual(root.succ(root.at(2), {wraparound: true}).attributes,
root.at(3).attributes,
"wraparound should have no effect if not succ(last_record)");
});
test('successor', function () {
var root = new openerp.web.list.Collection();
root.proxy('first').add([{id: 1, value: 1}, {id: 2, value: 2}]);
root.proxy('second').add([{id: 3, value: 3}, {id: 4, value: 5}]);
root.proxy('third').add([{id: 5, value: 8}, {id: 6, value: 13}]);
deepEqual(root.succ(root.get(3)).attributes,
root.get(4).attributes,
"should get successor");
equal(root.succ(root.get(4)),
null,
"successors do not cross collections");
deepEqual(root.succ(root.get(4), {wraparound: true}).attributes,
root.get(3).attributes,
"should wraparound within a collection");
});
test('degenerate-predecessor', function () {
var root = new openerp.web.list.Collection([
{id: 1, value: 1},
{id: 2, value: 2},
{id: 3, value: 3},
{id: 4, value: 5},
{id: 5, value: 8}
]);
deepEqual(root.pred(root.at(2)).attributes,
root.at(1).attributes,
"should return the record at (index - 1) from the pivot");
equal(root.pred(root.at(0)), null,
"should return null as predecessor to first record");
deepEqual(root.pred(root.at(0), {wraparound: true}).attributes,
root.at(4).attributes,
"should return last record as predecessor to first record" +
" if wraparound is set");
deepEqual(root.pred(root.at(1), {wraparound: true}).attributes,
root.at(0).attributes,
"wraparound should have no effect if not pred(first_record)");
});
test('predecessor', function () {
var root = new openerp.web.list.Collection();
root.proxy('first').add([{id: 1, value: 1}, {id: 2, value: 2}]);
root.proxy('second').add([{id: 3, value: 3}, {id: 4, value: 5}]);
root.proxy('third').add([{id: 5, value: 8}, {id: 6, value: 13}]);
deepEqual(root.pred(root.get(4)).attributes,
root.get(3).attributes,
"should get predecessor");
equal(root.pred(root.get(3)),
null,
"predecessor do not cross collections");
deepEqual(root.pred(root.get(3), {wraparound: true}).attributes,
root.get(4).attributes,
"should wraparound within a collection");
});
module('list-hofs', {
setup: function () {
@@ -338,4 +414,33 @@ $(document).ready(function () {
ids, [1, 2, 3, 10, 20, 30],
'tree collections should be deeply iterated');
});
module("list-weirds", {
setup: function () {
openerp = window.openerp.init([]);
window.openerp.web.corelib(openerp);
window.openerp.web.coresetup(openerp);
window.openerp.web.chrome(openerp);
// views loader stuff
window.openerp.web.data(openerp);
window.openerp.web.views(openerp);
window.openerp.web.list(openerp);
}
});
test('set-from-noid', function () {
var root = new openerp.web.list.Collection();
root.add({v: 3});
root.at(0).set('id', 42);
var record = root.get(42);
equal(root.length, 1);
equal(record.get('v'), 3, "should have fetched the original record");
});
test('set-from-previd', function () {
var root = new openerp.web.list.Collection();
root.add({id: 1, v: 2});
root.get(1).set('id', 42);
var record = root.get(42);
equal(root.length, 1);
equal(record.get('v'), 2, "should have fetched the original record");
});
});
-15
View File
@@ -9,21 +9,6 @@ $(document).ready(function () {
openerp.web.Foo2 = {};
}
});
test('key fetch', function () {
var reg = new openerp.web.Registry({
foo: 'openerp.web.Foo',
bar: 'openerp.web.Bar',
quux: 'openerp.web.Quux'
});
strictEqual(reg.get_object('foo'), openerp.web.Foo);
raises(function () { reg.get_object('qux'); },
openerp.web.KeyNotFound,
"Unknown keys should raise KeyNotFound");
raises(function () { reg.get_object('quux'); },
openerp.web.ObjectNotFound,
"Incorrect file paths should raise ObjectNotFound");
});
test('key set', function () {
var reg = new openerp.web.Registry();
+35 -103
View File
@@ -1,37 +1,8 @@
$(document).ready(function () {
var xhr = QWeb2.Engine.prototype.get_xhr();
xhr.open('GET', '/web/static/src/xml/base.xml', false);
xhr.send(null);
var doc = xhr.responseXML;
var noop = function () {};
/**
* Make connection RPC responses mockable by setting keys on the
* Connection#responses object (key is the URL, value is the function to
* call with the RPC request payload)
*
* @param {openerp.web.Connection} connection connection instance to mockify
* @param {Object} [responses] url:function mapping to seed the mock connection
*/
var mockifyRPC = function (connection, responses) {
connection.responses = responses || {};
connection.rpc_function = function (url, payload) {
if (!(url.url in this.responses)) {
return $.Deferred().reject({}, 'failed', _.str.sprintf("Url %s not found in mock responses", url.url)).promise();
}
return $.when(this.responses[url.url](payload));
};
};
var instance;
module('query', {
setup: function () {
instance = window.openerp.init([]);
window.openerp.web.corelib(instance);
window.openerp.web.coresetup(instance);
window.openerp.web.chrome(instance);
window.openerp.web.data(instance);
window.openerp.web.search(instance);
instance = openerp.testing.instanceFor('search');
}
});
test('Adding a facet to the query creates a facet and a value', function () {
@@ -167,16 +138,11 @@ $(document).ready(function () {
module('defaults', {
setup: function () {
instance = window.openerp.init([]);
window.openerp.web.corelib(instance);
window.openerp.web.coresetup(instance);
window.openerp.web.chrome(instance);
window.openerp.web.data(instance);
window.openerp.web.search(instance);
instance = openerp.testing.instanceFor('search');
instance.web.qweb.add_template(doc);
openerp.testing.loadTemplate(instance);
mockifyRPC(instance.connection);
openerp.testing.mockifyRPC(instance);
}
});
@@ -404,18 +370,11 @@ $(document).ready(function () {
module('completions', {
setup: function () {
instance = window.openerp.init([]);
window.openerp.web.corelib(instance);
window.openerp.web.coresetup(instance);
window.openerp.web.chrome(instance);
window.openerp.web.data(instance);
// date complete
window.openerp.web.formats(instance);
window.openerp.web.search(instance);
instance = openerp.testing.instanceFor('search');
instance.web.qweb.add_template(doc);
openerp.testing.loadTemplate(instance);
mockifyRPC(instance.connection);
openerp.testing.mockifyRPC(instance);
}
});
asyncTest('calling', 4, function () {
@@ -432,10 +391,7 @@ $(document).ready(function () {
}
});
view.appendTo($('#qunit-fixture'))
.always(start)
.fail(function (error) { ok(false, error.message); })
.done(function () {
stop();
view.complete_global_search({term: "dum"}, function (completions) {
start();
equal(completions.length, 1, "should have a single completion");
@@ -454,7 +410,11 @@ $(document).ready(function () {
var completion = {
label: "Dummy",
facet: {
field: {get_domain: noop, get_context: noop, get_groupby: noop},
field: {
get_domain: openerp.testing.noop,
get_context: openerp.testing.noop,
get_groupby: openerp.testing.noop
},
category: 'Dummy',
values: [{label: 'dummy', value: 42}]
}
@@ -476,7 +436,11 @@ $(document).ready(function () {
});
});
asyncTest('facet selection: new value existing facet', 3, function () {
var field = {get_domain: noop, get_context: noop, get_groupby: noop};
var field = {
get_domain: openerp.testing.noop,
get_context: openerp.testing.noop,
get_groupby: openerp.testing.noop
};
var completion = {
label: "Dummy",
facet: {
@@ -663,16 +627,11 @@ $(document).ready(function () {
module('search-serialization', {
setup: function () {
instance = window.openerp.init([]);
window.openerp.web.corelib(instance);
window.openerp.web.coresetup(instance);
window.openerp.web.chrome(instance);
window.openerp.web.data(instance);
window.openerp.web.search(instance);
instance = openerp.testing.instanceFor('search');
instance.web.qweb.add_template(doc);
openerp.testing.loadTemplate(instance);
mockifyRPC(instance.connection);
openerp.testing.mockifyRPC(instance);
}
});
asyncTest('No facet, no call', 6, function () {
@@ -940,16 +899,11 @@ $(document).ready(function () {
module('removal', {
setup: function () {
instance = window.openerp.init([]);
window.openerp.web.corelib(instance);
window.openerp.web.coresetup(instance);
window.openerp.web.chrome(instance);
window.openerp.web.data(instance);
window.openerp.web.search(instance);
instance = openerp.testing.instanceFor('search');
instance.web.qweb.add_template(doc);
openerp.testing.loadTemplate(instance);
mockifyRPC(instance.connection);
openerp.testing.mockifyRPC(instance);
}
});
asyncTest('clear button', function () {
@@ -975,16 +929,11 @@ $(document).ready(function () {
module('drawer', {
setup: function () {
instance = window.openerp.init([]);
window.openerp.web.corelib(instance);
window.openerp.web.coresetup(instance);
window.openerp.web.chrome(instance);
window.openerp.web.data(instance);
window.openerp.web.search(instance);
instance = openerp.testing.instanceFor('search');
instance.web.qweb.add_template(doc);
openerp.testing.loadTemplate(instance);
mockifyRPC(instance.connection);
openerp.testing.mockifyRPC(instance);
}
});
asyncTest('is-drawn', 2, function () {
@@ -1003,16 +952,11 @@ $(document).ready(function () {
module('filters', {
setup: function () {
instance = window.openerp.init([]);
window.openerp.web.corelib(instance);
window.openerp.web.coresetup(instance);
window.openerp.web.chrome(instance);
window.openerp.web.data(instance);
window.openerp.web.search(instance);
instance = openerp.testing.instanceFor('search');
instance.web.qweb.add_template(doc);
openerp.testing.loadTemplate(instance);
mockifyRPC(instance.connection, {
openerp.testing.mockifyRPC(instance, {
'/web/searchview/load': function () {
// view with a single group of filters
return {result: {fields_view: {
@@ -1117,17 +1061,11 @@ $(document).ready(function () {
module('saved_filters', {
setup: function () {
instance = window.openerp.init([]);
window.openerp.web.corelib(instance);
window.openerp.web.coresetup(instance);
window.openerp.web.chrome(instance);
window.openerp.web.data(instance);
window.openerp.web.formats(instance);
window.openerp.web.search(instance);
instance = openerp.testing.instanceFor('search');
instance.web.qweb.add_template(doc);
openerp.testing.loadTemplate(instance);
mockifyRPC(instance.connection);
openerp.testing.mockifyRPC(instance);
}
});
asyncTest('checkboxing', 6, function () {
@@ -1183,17 +1121,11 @@ $(document).ready(function () {
module('advanced', {
setup: function () {
instance = window.openerp.init([]);
window.openerp.web.corelib(instance);
window.openerp.web.coresetup(instance);
window.openerp.web.chrome(instance);
window.openerp.web.data(instance);
window.openerp.web.formats(instance);
window.openerp.web.search(instance);
instance = openerp.testing.instanceFor('search');
instance.web.qweb.add_template(doc);
openerp.testing.loadTemplate(instance);
mockifyRPC(instance.connection);
openerp.testing.mockifyRPC(instance);
}
});
asyncTest('single-advanced', 6, function () {
+9 -1
View File
@@ -13,7 +13,7 @@
<script src="/web/static/lib/backbone/backbone.js" type="text/javascript"></script>
<!-- jquery -->
<script src="/web/static/lib/jquery/jquery-1.7.2b1.js"></script>
<script src="/web/static/lib/jquery/jquery-1.7.2.js"></script>
<script src="/web/static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js"></script>
<script src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script>
@@ -38,6 +38,12 @@
<script src="/web/static/src/js/search.js"></script>
<script src="/web/static/src/js/view_form.js"></script>
<script src="/web/static/src/js/view_list.js"></script>
<script src="/web/static/src/js/view_list_editable.js"></script>
<script src="/web/static/test/testing.js"></script>
<script type="text/javascript">
QUnit.config.testTimeout = 2000;
</script>
</head>
<body id="oe" class="openerp">
<h1 id="qunit-header">OpenERP web Test Suite</h1>
@@ -55,4 +61,6 @@
<script type="text/javascript" src="/web/static/test/rpc.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/Widget.js"></script>
<script type="text/javascript" src="/web/static/test/list-editable.js"></script>
</html>
+97
View File
@@ -0,0 +1,97 @@
// Test support structures and methods for OpenERP
openerp.testing = (function () {
var xhr = QWeb2.Engine.prototype.get_xhr();
xhr.open('GET', '/web/static/src/xml/base.xml', false);
xhr.send(null);
var doc = xhr.responseXML;
var dependencies = {
corelib: [],
coresetup: ['corelib'],
data: ['corelib', 'coresetup'],
dates: [],
formats: ['coresetup', 'dates'],
chrome: ['corelib', 'coresetup'],
views: ['corelib', 'coresetup', 'data', 'chrome'],
search: ['data', 'coresetup', 'formats'],
list: ['views', 'data'],
form: ['data', 'views', 'list', 'formats'],
list_editable: ['list', 'form', 'data'],
};
return {
/**
* Function which does not do anything
*/
noop: function () { },
/**
* Loads 'base.xml' template file into qweb for the provided instance
*
* @param instance openerp instance being initialized, to load the template file in
*/
loadTemplate: function (instance) {
instance.web.qweb.add_template(doc);
},
/**
* Alter provided instance's ``connection`` attribute to make response
* mockable:
*
* * The ``responses`` parameter can be used to provide a map of (RPC)
* paths (e.g. ``/web/view/load``) to a function returning a response
* to the query.
* * ``instance,connection`` grows a ``responses`` attribute which is
* a map of the same (and is in fact initialized to the ``responses``
* parameter if one is provided)
*
* Note that RPC requests to un-mocked URLs will be rejected with an
* error message: only explicitly specified urls will get a response.
*
* Mocked connections will *never* perform an actual RPC connection.
*
* @param instance openerp instance being initialized
* @param {Object} [responses]
*/
mockifyRPC: function (instance, responses) {
var connection = instance.connection;
connection.responses = responses || {};
connection.rpc_function = function (url, payload) {
var fn = this.responses[url.url + ':' + payload.params.method]
|| this.responses[url.url];
if (!fn) {
return $.Deferred().reject({}, 'failed',
_.str.sprintf("Url %s not found in mock responses, with arguments %s",
url.url, JSON.stringify(payload.params))
).promise();
}
return $.when(fn(payload));
};
},
/**
* Creates an openerp web instance loading the specified module after
* all of its dependencies.
*
* @param {String} module
* @returns OpenERP Web instance
*/
instanceFor: function (module) {
var instance = openerp.init([]);
this._load(instance, module);
return instance;
},
_load: function (instance, module, loaded) {
if (!loaded) { loaded = []; }
var deps = dependencies[module];
if (!deps) { throw new Error("Unknown dependencies for " + module); }
var to_load = _.difference(deps, loaded);
while (!_.isEmpty(to_load)) {
this._load(instance, to_load[0], loaded);
to_load = _.difference(deps, loaded);
}
openerp.web[module](instance);
loaded.push(module);
}
}
})();
+1 -4
View File
@@ -1,10 +1,7 @@
{
"name": "Web Calendar",
"category": "Hidden",
"description":
"""
OpenERP Web Calendar view.
""",
"description":"""OpenERP Web Calendar view.""",
"version": "2.0",
"depends": ['web'],
"js": [
+67 -67
View File
@@ -14,129 +14,129 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:45+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "التقويم"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
msgid "New event"
msgstr ""
msgstr "مرشّح"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Save"
msgstr ""
msgid "Today"
msgstr "اليوم"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Cancel"
msgstr ""
msgid "Day"
msgstr "اليوم"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Details"
msgstr ""
msgid "Week"
msgstr "الأسبوع"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Edit"
msgstr ""
msgid "Month"
msgstr "الشهر"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "Delete"
msgstr ""
msgid "New event"
msgstr "حدث جديد"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr "حفظ"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
msgid "Cancel"
msgstr "إلغاء"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Description"
msgstr ""
msgid "Details"
msgstr "التفاصيل"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Time period"
msgstr ""
msgid "Edit"
msgstr "تحرير"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Full day"
msgstr ""
msgid "Delete"
msgstr "حذف"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr "سيتم حذف هذا الحدث بشكل دائم، هل أنت متأكد؟"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr "الوصف"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Repeat event"
msgstr ""
msgid "Time period"
msgstr "الفترة الزمنية"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Disabled"
msgstr ""
msgid "Full day"
msgstr "يوم كامل"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
msgid "Enabled"
msgstr ""
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr "هل تريد تحرير مجموعة الأحداث المتكررة كاملة؟"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
msgid "Agenda"
msgstr ""
msgid "Repeat event"
msgstr "تكرار الحدث"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Date"
msgstr ""
msgid "Disabled"
msgstr "معطّل"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr "مُفعّل"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
msgid "Year"
msgstr ""
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr "جدول أعمال"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr "التاريخ"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr "السنة"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+68 -68
View File
@@ -14,131 +14,131 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:45+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Календар"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
msgid "New event"
msgstr ""
msgstr "Филтър"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Save"
msgstr ""
msgid "Today"
msgstr "Днес"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Cancel"
msgstr ""
msgid "Day"
msgstr "Ден"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Details"
msgstr ""
msgid "Week"
msgstr "Седмица"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Edit"
msgstr ""
msgid "Month"
msgstr "Месец"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "Delete"
msgstr ""
msgid "New event"
msgstr "Ново събитие"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr "Запис"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
msgid "Cancel"
msgstr "Отказ"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Description"
msgstr ""
msgid "Details"
msgstr "Детайли"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Time period"
msgstr ""
msgid "Edit"
msgstr "Редакция"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Full day"
msgstr ""
msgid "Delete"
msgstr "Изтриване"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr "Събитието ще бъде окончателно изтрито, сигурни ли сте?"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr "Описание"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Repeat event"
msgstr ""
msgid "Time period"
msgstr "Времеви период"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Disabled"
msgstr ""
msgid "Full day"
msgstr "Цял ден"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
msgid "Enabled"
msgstr ""
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr "Искатели да редактирате всички повтарящи се събития?"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
msgid "Agenda"
msgstr ""
msgid "Repeat event"
msgstr "Повтаряне на събитие"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Date"
msgstr ""
msgid "Disabled"
msgstr "Изключено"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr "Включено"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
msgid "Year"
msgstr ""
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr "Дневен ред"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr "Дата"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr "Година"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr ""
msgstr "&nbsp;"
#~ msgid "Navigator"
#~ msgstr "Навигатор"
+29 -29
View File
@@ -14,129 +14,129 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:45+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "পুঞ্জিকা"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+29 -29
View File
@@ -14,129 +14,129 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:45+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Kalendar"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+29 -29
View File
@@ -14,128 +14,128 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:45+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr ""
+29 -29
View File
@@ -14,130 +14,130 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:45+0000\n"
"X-Generator: Launchpad (build 15757)\n"
"X-Poedit-Language: Czech\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Kalendář"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+29 -29
View File
@@ -14,129 +14,129 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:45+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Kalender"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+29 -29
View File
@@ -14,129 +14,129 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:45+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Kalender"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+29 -29
View File
@@ -14,129 +14,129 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:46+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Calendar"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+29 -29
View File
@@ -14,129 +14,129 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:46+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Calendar"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+29 -29
View File
@@ -14,129 +14,129 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:46+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Calendario"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+29 -29
View File
@@ -14,129 +14,129 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:46+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Calendario"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+29 -29
View File
@@ -15,130 +15,130 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:46+0000\n"
"X-Generator: Launchpad (build 15757)\n"
"Language: es\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Calendario"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"
+29 -29
View File
@@ -14,129 +14,129 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-07-03 05:55+0000\n"
"X-Generator: Launchpad (build 15531)\n"
"X-Launchpad-Export-Date: 2012-08-08 04:46+0000\n"
"X-Generator: Launchpad (build 15757)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:12
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Calendario"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:73
#: addons/web_calendar/static/src/js/calendar.js:70
msgid "Filter"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:139
#: addons/web_calendar/static/src/js/calendar.js:144
msgid "Today"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:140
#: addons/web_calendar/static/src/js/calendar.js:145
msgid "Day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:141
#: addons/web_calendar/static/src/js/calendar.js:146
msgid "Week"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:142
#: addons/web_calendar/static/src/js/calendar.js:147
msgid "Month"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:143
#: addons/web_calendar/static/src/js/calendar.js:148
msgid "New event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:144
#: addons/web_calendar/static/src/js/calendar.js:149
msgid "Save"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:145
#: addons/web_calendar/static/src/js/calendar.js:150
msgid "Cancel"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:146
#: addons/web_calendar/static/src/js/calendar.js:151
msgid "Details"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:147
#: addons/web_calendar/static/src/js/calendar.js:152
msgid "Edit"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:148
#: addons/web_calendar/static/src/js/calendar.js:153
msgid "Delete"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:150
#: addons/web_calendar/static/src/js/calendar.js:155
msgid "Event will be deleted permanently, are you sure?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:151
#: addons/web_calendar/static/src/js/calendar.js:164
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:169
msgid "Description"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:152
#: addons/web_calendar/static/src/js/calendar.js:157
msgid "Time period"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:153
#: addons/web_calendar/static/src/js/calendar.js:158
msgid "Full day"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:156
#: addons/web_calendar/static/src/js/calendar.js:161
msgid "Do you want to edit the whole set of repeated events?"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:157
#: addons/web_calendar/static/src/js/calendar.js:162
msgid "Repeat event"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:158
#: addons/web_calendar/static/src/js/calendar.js:163
msgid "Disabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:159
#: addons/web_calendar/static/src/js/calendar.js:164
msgid "Enabled"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:162
#: addons/web_calendar/static/src/js/calendar.js:170
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:175
msgid "Agenda"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:163
#: addons/web_calendar/static/src/js/calendar.js:168
msgid "Date"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:167
#: addons/web_calendar/static/src/js/calendar.js:172
msgid "Year"
msgstr ""
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"

Some files were not shown because too many files have changed in this diff Show More