[MERGE] from trunk, fix/adapt some tests
bzr revid: xmo@openerp.com-20121116100840-yyr9b4oru3zdftld
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
'name': 'Web',
|
||||
'category': 'Hidden',
|
||||
'version': '7.0.1.0',
|
||||
'description':
|
||||
"""
|
||||
OpenERP Web core module.
|
||||
|
@ -17,7 +18,7 @@ This module provides the core of the OpenERP Web Client.
|
|||
"static/lib/datejs/parser.js",
|
||||
"static/lib/datejs/sugarpak.js",
|
||||
"static/lib/datejs/extras.js",
|
||||
"static/lib/jquery/jquery-1.7.2.js",
|
||||
"static/lib/jquery/jquery-1.8.2.js",
|
||||
"static/lib/jquery.MD5/jquery.md5.js",
|
||||
"static/lib/jquery.form/jquery.form.js",
|
||||
"static/lib/jquery.validate/jquery.validate.js",
|
||||
|
@ -25,7 +26,7 @@ This module provides the core of the OpenERP Web Client.
|
|||
"static/lib/spinjs/spin.js",
|
||||
"static/lib/jquery.autosize/jquery.autosize.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/js/jquery-ui-1.9.1.custom.js",
|
||||
"static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js",
|
||||
"static/lib/jquery.ui.notify/js/jquery.notify.js",
|
||||
"static/lib/jquery.deferred-queue/jquery.deferred-queue.js",
|
||||
|
@ -38,7 +39,7 @@ This module provides the core of the OpenERP Web Client.
|
|||
"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/lib/py.js/lib/py.js",
|
||||
"static/src/js/boot.js",
|
||||
"static/src/js/testing.js",
|
||||
"static/src/js/corelib.js",
|
||||
|
@ -56,7 +57,7 @@ This module provides the core of the OpenERP Web Client.
|
|||
"static/src/js/view_tree.js",
|
||||
],
|
||||
'css' : [
|
||||
"static/lib/jquery.ui.bootstrap/css/custom-theme/jquery-ui-1.8.16.custom.css",
|
||||
"static/lib/jquery.ui.bootstrap/css/custom-theme/jquery-ui-1.9.0.custom.css",
|
||||
"static/lib/jquery.ui.timepicker/css/jquery-ui-timepicker-addon.css",
|
||||
"static/lib/jquery.ui.notify/css/ui.notify.css",
|
||||
"static/lib/jquery.tipsy/tipsy.css",
|
||||
|
@ -79,6 +80,9 @@ This module provides the core of the OpenERP Web Client.
|
|||
"static/test/evals.js",
|
||||
"static/test/search.js",
|
||||
"static/test/Widget.js",
|
||||
"static/test/list.js"
|
||||
"static/test/list-editable.js"
|
||||
],
|
||||
'bootstrap': True,
|
||||
'twitter': False,
|
||||
}
|
||||
|
|
|
@ -81,57 +81,6 @@ def rjsmin(script):
|
|||
).strip()
|
||||
return result
|
||||
|
||||
def sass2scss(src):
|
||||
# Validated by diff -u of sass2scss against:
|
||||
# sass-convert -F sass -T scss openerp.sass openerp.scss
|
||||
block = []
|
||||
sass = ('', block)
|
||||
reComment = re.compile(r'//.*$')
|
||||
reIndent = re.compile(r'^\s+')
|
||||
reIgnore = re.compile(r'^\s*(//.*)?$')
|
||||
reFixes = { re.compile(r'\(\((.*)\)\)') : r'(\1)', }
|
||||
lastLevel = 0
|
||||
prevBlocks = {}
|
||||
for l in src.split('\n'):
|
||||
l = l.rstrip()
|
||||
if reIgnore.search(l): continue
|
||||
l = reComment.sub('', l)
|
||||
l = l.rstrip()
|
||||
indent = reIndent.match(l)
|
||||
level = indent.end() if indent else 0
|
||||
l = l[level:]
|
||||
if level>lastLevel:
|
||||
prevBlocks[lastLevel] = block
|
||||
newBlock = []
|
||||
block[-1] = (block[-1], newBlock)
|
||||
block = newBlock
|
||||
elif level<lastLevel:
|
||||
block = prevBlocks[level]
|
||||
lastLevel = level
|
||||
if not l: continue
|
||||
# Fixes
|
||||
for ereg, repl in reFixes.items():
|
||||
l = ereg.sub(repl if type(repl)==str else repl(), l)
|
||||
block.append(l)
|
||||
|
||||
def write(sass, level=-1):
|
||||
out = ""
|
||||
indent = ' '*level
|
||||
if type(sass)==tuple:
|
||||
if level>=0:
|
||||
out += indent+sass[0]+" {\n"
|
||||
for e in sass[1]:
|
||||
out += write(e, level+1)
|
||||
if level>=0:
|
||||
out = out.rstrip(" \n")
|
||||
out += ' }\n'
|
||||
if level==0:
|
||||
out += "\n"
|
||||
else:
|
||||
out += indent+sass+";\n"
|
||||
return out
|
||||
return write(sass)
|
||||
|
||||
def db_list(req):
|
||||
dbs = []
|
||||
proxy = req.session.proxy("db")
|
||||
|
@ -142,6 +91,17 @@ def db_list(req):
|
|||
dbs = [i for i in dbs if re.match(r, i)]
|
||||
return dbs
|
||||
|
||||
def db_monodb(req):
|
||||
# if only one db is listed returns it else return False
|
||||
try:
|
||||
dbs = db_list(req)
|
||||
if len(dbs) == 1:
|
||||
return dbs[0]
|
||||
except xmlrpclib.Fault:
|
||||
# ignore access denied
|
||||
pass
|
||||
return False
|
||||
|
||||
def module_topological_sort(modules):
|
||||
""" Return a list of module names sorted so that their dependencies of the
|
||||
modules are listed before the module itself
|
||||
|
@ -231,22 +191,14 @@ def module_installed_bypass_session(dbname):
|
|||
|
||||
def module_boot(req):
|
||||
server_wide_modules = openerp.conf.server_wide_modules or ['web']
|
||||
return [m for m in server_wide_modules if m in openerpweb.addons_manifest]
|
||||
# TODO the following will be enabled once we separate the module code and translation loading
|
||||
serverside = []
|
||||
dbside = []
|
||||
for i in server_wide_modules:
|
||||
if i in openerpweb.addons_manifest:
|
||||
serverside.append(i)
|
||||
# if only one db load every module at boot
|
||||
dbs = []
|
||||
try:
|
||||
dbs = db_list(req)
|
||||
except xmlrpclib.Fault:
|
||||
# ignore access denied
|
||||
pass
|
||||
if len(dbs) == 1:
|
||||
dbside = module_installed_bypass_session(dbs[0])
|
||||
monodb = db_monodb(req)
|
||||
if monodb:
|
||||
dbside = module_installed_bypass_session(monodb)
|
||||
dbside = [i for i in dbside if i not in serverside]
|
||||
addons = serverside + dbside
|
||||
return addons
|
||||
|
@ -311,6 +263,10 @@ def concat_js(file_list):
|
|||
content = rjsmin(content)
|
||||
return content, checksum
|
||||
|
||||
def fs2web(path):
|
||||
"""convert FS path into web path"""
|
||||
return '/'.join(path.split(os.path.sep))
|
||||
|
||||
def manifest_glob(req, addons, key):
|
||||
if addons is None:
|
||||
addons = module_boot(req)
|
||||
|
@ -326,7 +282,7 @@ def manifest_glob(req, addons, key):
|
|||
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):]))
|
||||
r.append((path, fs2web(path[len(addons_path):])))
|
||||
return r
|
||||
|
||||
def manifest_list(req, mods, extension):
|
||||
|
@ -549,7 +505,7 @@ def _local_web_translations(trans_file):
|
|||
messages.append({'id': x.id, 'string': x.string})
|
||||
return messages
|
||||
|
||||
def from_elementtree(el, preserve_whitespaces=False):
|
||||
def xml2json_from_elementtree(el, preserve_whitespaces=False):
|
||||
""" xml2json-direct
|
||||
Simple and straightforward XML-to-JSON converter in Python
|
||||
New BSD Licensed
|
||||
|
@ -569,12 +525,25 @@ def from_elementtree(el, preserve_whitespaces=False):
|
|||
if el.text and (preserve_whitespaces or el.text.strip() != ''):
|
||||
kids.append(el.text)
|
||||
for kid in el:
|
||||
kids.append(from_elementtree(kid, preserve_whitespaces))
|
||||
kids.append(xml2json_from_elementtree(kid, preserve_whitespaces))
|
||||
if kid.tail and (preserve_whitespaces or kid.tail.strip() != ''):
|
||||
kids.append(kid.tail)
|
||||
res["children"] = kids
|
||||
return res
|
||||
|
||||
def content_disposition(filename, req):
|
||||
filename = filename.encode('utf8')
|
||||
escaped = urllib2.quote(filename)
|
||||
browser = req.httprequest.user_agent.browser
|
||||
version = int((req.httprequest.user_agent.version or '0').split('.')[0])
|
||||
if browser == 'msie' and version < 9:
|
||||
return "attachment; filename=%s" % escaped
|
||||
elif browser == 'safari':
|
||||
return "attachment; filename=%s" % filename
|
||||
else:
|
||||
return "attachment; filename*=UTF-8''%s" % escaped
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
# OpenERP Web web Controllers
|
||||
#----------------------------------------------------------
|
||||
|
@ -598,8 +567,7 @@ html_template = """<!DOCTYPE html>
|
|||
</head>
|
||||
<body>
|
||||
<!--[if lte IE 8]>
|
||||
<script type="text/javascript"
|
||||
src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
|
||||
<script>
|
||||
var test = function() {
|
||||
CFInstall.check({
|
||||
|
@ -673,8 +641,7 @@ class WebClient(openerpweb.Controller):
|
|||
data = fp.read().decode('utf-8')
|
||||
|
||||
path = file_map[f]
|
||||
# convert FS path into web path
|
||||
web_dir = '/'.join(os.path.dirname(path).split(os.path.sep))
|
||||
web_dir = os.path.dirname(path)
|
||||
|
||||
data = re.sub(
|
||||
rx_import,
|
||||
|
@ -727,21 +694,20 @@ class WebClient(openerpweb.Controller):
|
|||
until we have established a valid session. This is meant only
|
||||
for translating the login page and db management chrome, using
|
||||
the browser's language. """
|
||||
lang = req.httprequest.accept_languages.best or 'en'
|
||||
# For performance reasons we only load a single translation, so for
|
||||
# sub-languages (that should only be partially translated) we load the
|
||||
# main language PO instead - that should be enough for the login screen.
|
||||
if '-' in lang: # RFC2616 uses '-' separators for sublanguages
|
||||
lang = lang.split('-')[0]
|
||||
lang = req.lang.split('_')[0]
|
||||
|
||||
translations_per_module = {}
|
||||
for addon_name in mods:
|
||||
addons_path = openerpweb.addons_manifest[addon_name]['addons_path']
|
||||
f_name = os.path.join(addons_path, addon_name, "i18n", lang + ".po")
|
||||
if not os.path.exists(f_name):
|
||||
continue
|
||||
translations_per_module[addon_name] = {'messages': _local_web_translations(f_name)}
|
||||
|
||||
if openerpweb.addons_manifest[addon_name].get('bootstrap'):
|
||||
addons_path = openerpweb.addons_manifest[addon_name]['addons_path']
|
||||
f_name = os.path.join(addons_path, addon_name, "i18n", lang + ".po")
|
||||
if not os.path.exists(f_name):
|
||||
continue
|
||||
translations_per_module[addon_name] = {'messages': _local_web_translations(f_name)}
|
||||
|
||||
return {"modules": translations_per_module,
|
||||
"lang_parameters": None}
|
||||
|
||||
|
@ -805,15 +771,20 @@ class Database(openerpweb.Controller):
|
|||
@openerpweb.jsonrequest
|
||||
def create(self, req, fields):
|
||||
params = dict(map(operator.itemgetter('name', 'value'), fields))
|
||||
create_attrs = (
|
||||
return req.session.proxy("db").create_database(
|
||||
params['super_admin_pwd'],
|
||||
params['db_name'],
|
||||
bool(params.get('demo_data')),
|
||||
params['db_lang'],
|
||||
params['create_admin_pwd']
|
||||
)
|
||||
params['create_admin_pwd'])
|
||||
|
||||
return req.session.proxy("db").create_database(*create_attrs)
|
||||
@openerpweb.jsonrequest
|
||||
def duplicate(self, req, fields):
|
||||
params = dict(map(operator.itemgetter('name', 'value'), fields))
|
||||
return req.session.proxy("db").duplicate_database(
|
||||
params['super_admin_pwd'],
|
||||
params['db_original_name'],
|
||||
params['db_name'])
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def duplicate(self, req, fields):
|
||||
|
@ -851,7 +822,7 @@ class Database(openerpweb.Controller):
|
|||
}
|
||||
return req.make_response(db_dump,
|
||||
[('Content-Type', 'application/octet-stream; charset=binary'),
|
||||
('Content-Disposition', 'attachment; filename="' + filename + '"')],
|
||||
('Content-Disposition', content_disposition(filename, req))],
|
||||
{'fileToken': int(token)}
|
||||
)
|
||||
except xmlrpclib.Fault, e:
|
||||
|
@ -1291,17 +1262,6 @@ class DataSet(openerpweb.Controller):
|
|||
m.write(id, { field: i + offset })
|
||||
return True
|
||||
|
||||
class DataGroup(openerpweb.Controller):
|
||||
_cp_path = "/web/group"
|
||||
@openerpweb.jsonrequest
|
||||
def read(self, req, model, fields, group_by_fields, domain=None, sort=None):
|
||||
Model = req.session.model(model)
|
||||
context, domain = eval_context_and_domain(req.session, req.context, domain)
|
||||
|
||||
return Model.read_group(
|
||||
domain or [], fields, group_by_fields, 0, False,
|
||||
dict(context, group_by=group_by_fields), sort or False)
|
||||
|
||||
class View(openerpweb.Controller):
|
||||
_cp_path = "/web/view"
|
||||
|
||||
|
@ -1335,7 +1295,7 @@ class View(openerpweb.Controller):
|
|||
xml = self.transform_view(arch, session, evaluation_context)
|
||||
else:
|
||||
xml = ElementTree.fromstring(arch)
|
||||
fvg['arch'] = from_elementtree(xml, preserve_whitespaces)
|
||||
fvg['arch'] = xml2json_from_elementtree(xml, preserve_whitespaces)
|
||||
|
||||
if 'id' in fvg['fields']:
|
||||
# Special case for id's
|
||||
|
@ -1509,11 +1469,24 @@ class Binary(openerpweb.Controller):
|
|||
try:
|
||||
if not id:
|
||||
res = Model.default_get([field], context).get(field)
|
||||
image_data = base64.b64decode(res)
|
||||
image_base64 = res
|
||||
else:
|
||||
res = Model.read([id], [last_update, field], context)[0]
|
||||
retag = hashlib.md5(res.get(last_update)).hexdigest()
|
||||
image_data = base64.b64decode(res.get(field))
|
||||
image_base64 = res.get(field)
|
||||
|
||||
if kw.get('resize'):
|
||||
resize = kw.get('resize').split(',');
|
||||
if len(resize) == 2 and int(resize[0]) and int(resize[1]):
|
||||
width = int(resize[0])
|
||||
height = int(resize[1])
|
||||
# resize maximum 500*500
|
||||
if width > 500: width = 500
|
||||
if height > 500: height = 500
|
||||
image_base64 = openerp.tools.image_resize_image(base64_source=image_base64, size=(width, height), encoding='base64', filetype='PNG')
|
||||
|
||||
image_data = base64.b64decode(image_base64)
|
||||
|
||||
except (TypeError, xmlrpclib.Fault):
|
||||
image_data = self.placeholder(req)
|
||||
headers.append(('ETag', retag))
|
||||
|
@ -1527,17 +1500,6 @@ class Binary(openerpweb.Controller):
|
|||
def placeholder(self, req):
|
||||
addons_path = openerpweb.addons_manifest['web']['addons_path']
|
||||
return open(os.path.join(addons_path, 'web', 'static', 'src', 'img', 'placeholder.png'), 'rb').read()
|
||||
def content_disposition(self, filename, req):
|
||||
filename = filename.encode('utf8')
|
||||
escaped = urllib2.quote(filename)
|
||||
browser = req.httprequest.user_agent.browser
|
||||
version = int((req.httprequest.user_agent.version or '0').split('.')[0])
|
||||
if browser == 'msie' and version < 9:
|
||||
return "attachment; filename=%s" % escaped
|
||||
elif browser == 'safari':
|
||||
return "attachment; filename=%s" % filename
|
||||
else:
|
||||
return "attachment; filename*=UTF-8''%s" % escaped
|
||||
|
||||
@openerpweb.httprequest
|
||||
def saveas(self, req, model, field, id=None, filename_field=None, **kw):
|
||||
|
@ -1573,7 +1535,7 @@ class Binary(openerpweb.Controller):
|
|||
filename = res.get(filename_field, '') or filename
|
||||
return req.make_response(filecontent,
|
||||
[('Content-Type', 'application/octet-stream'),
|
||||
('Content-Disposition', self.content_disposition(filename, req))])
|
||||
('Content-Disposition', content_disposition(filename, req))])
|
||||
|
||||
@openerpweb.httprequest
|
||||
def saveas_ajax(self, req, data, token):
|
||||
|
@ -1603,7 +1565,7 @@ class Binary(openerpweb.Controller):
|
|||
filename = res.get(filename_field, '') or filename
|
||||
return req.make_response(filecontent,
|
||||
headers=[('Content-Type', 'application/octet-stream'),
|
||||
('Content-Disposition', self.content_disposition(filename, req))],
|
||||
('Content-Disposition', content_disposition(filename, req))],
|
||||
cookies={'fileToken': int(token)})
|
||||
|
||||
@openerpweb.httprequest
|
||||
|
@ -1868,7 +1830,8 @@ class Export(View):
|
|||
|
||||
|
||||
return req.make_response(self.from_data(columns_headers, import_data),
|
||||
headers=[('Content-Disposition', 'attachment; filename="%s"' % self.filename(model)),
|
||||
headers=[('Content-Disposition',
|
||||
content_disposition(self.filename(model), req)),
|
||||
('Content-Type', self.content_type)],
|
||||
cookies={'fileToken': int(token)})
|
||||
|
||||
|
@ -2004,121 +1967,13 @@ class Reports(View):
|
|||
file_name = reports.read(res_id[0], ['name'], context)['name']
|
||||
else:
|
||||
file_name = action['report_name']
|
||||
file_name = '%s.%s' % (file_name, report_struct['format'])
|
||||
|
||||
return req.make_response(report,
|
||||
headers=[
|
||||
# maybe we should take of what characters can appear in a file name?
|
||||
('Content-Disposition', 'attachment; filename="%s.%s"' % (file_name, report_struct['format'])),
|
||||
('Content-Disposition', content_disposition(file_name, req)),
|
||||
('Content-Type', report_mimetype),
|
||||
('Content-Length', len(report))],
|
||||
cookies={'fileToken': int(token)})
|
||||
|
||||
class Import(View):
|
||||
_cp_path = "/web/import"
|
||||
|
||||
def fields_get(self, req, model):
|
||||
Model = req.session.model(model)
|
||||
fields = Model.fields_get(False, req.session.eval_context(req.context))
|
||||
return fields
|
||||
|
||||
@openerpweb.httprequest
|
||||
def detect_data(self, req, csvfile, csvsep=',', csvdel='"', csvcode='utf-8', jsonp='callback'):
|
||||
try:
|
||||
data = list(csv.reader(
|
||||
csvfile, quotechar=str(csvdel), delimiter=str(csvsep)))
|
||||
except csv.Error, e:
|
||||
csvfile.seek(0)
|
||||
return '<script>window.top.%s(%s);</script>' % (
|
||||
jsonp, simplejson.dumps({'error': {
|
||||
'message': 'Error parsing CSV file: %s' % e,
|
||||
# decodes each byte to a unicode character, which may or
|
||||
# may not be printable, but decoding will succeed.
|
||||
# Otherwise simplejson will try to decode the `str` using
|
||||
# utf-8, which is very likely to blow up on characters out
|
||||
# of the ascii range (in range [128, 256))
|
||||
'preview': csvfile.read(200).decode('iso-8859-1')}}))
|
||||
|
||||
try:
|
||||
return '<script>window.top.%s(%s);</script>' % (
|
||||
jsonp, simplejson.dumps(
|
||||
{'records': data[:10]}, encoding=csvcode))
|
||||
except UnicodeDecodeError:
|
||||
return '<script>window.top.%s(%s);</script>' % (
|
||||
jsonp, simplejson.dumps({
|
||||
'message': u"Failed to decode CSV file using encoding %s, "
|
||||
u"try switching to a different encoding" % csvcode
|
||||
}))
|
||||
|
||||
@openerpweb.httprequest
|
||||
def import_data(self, req, model, csvfile, csvsep, csvdel, csvcode, jsonp,
|
||||
meta):
|
||||
modle_obj = req.session.model(model)
|
||||
skip, indices, fields = operator.itemgetter('skip', 'indices', 'fields')(
|
||||
simplejson.loads(meta))
|
||||
|
||||
error = None
|
||||
if not (csvdel and len(csvdel) == 1):
|
||||
error = u"The CSV delimiter must be a single character"
|
||||
|
||||
if not indices and fields:
|
||||
error = u"You must select at least one field to import"
|
||||
|
||||
if error:
|
||||
return '<script>window.top.%s(%s);</script>' % (
|
||||
jsonp, simplejson.dumps({'error': {'message': error}}))
|
||||
|
||||
# skip ignored records (@skip parameter)
|
||||
# then skip empty lines (not valid csv)
|
||||
# nb: should these operations be reverted?
|
||||
rows_to_import = itertools.ifilter(
|
||||
None,
|
||||
itertools.islice(
|
||||
csv.reader(csvfile, quotechar=str(csvdel), delimiter=str(csvsep)),
|
||||
skip, None))
|
||||
|
||||
# if only one index, itemgetter will return an atom rather than a tuple
|
||||
if len(indices) == 1: mapper = lambda row: [row[indices[0]]]
|
||||
else: mapper = operator.itemgetter(*indices)
|
||||
|
||||
data = None
|
||||
error = None
|
||||
try:
|
||||
# decode each data row
|
||||
data = [
|
||||
[record.decode(csvcode) for record in row]
|
||||
for row in itertools.imap(mapper, rows_to_import)
|
||||
# don't insert completely empty rows (can happen due to fields
|
||||
# filtering in case of e.g. o2m content rows)
|
||||
if any(row)
|
||||
]
|
||||
except UnicodeDecodeError:
|
||||
error = u"Failed to decode CSV file using encoding %s" % csvcode
|
||||
except csv.Error, e:
|
||||
error = u"Could not process CSV file: %s" % e
|
||||
|
||||
# If the file contains nothing,
|
||||
if not data:
|
||||
error = u"File to import is empty"
|
||||
if error:
|
||||
return '<script>window.top.%s(%s);</script>' % (
|
||||
jsonp, simplejson.dumps({'error': {'message': error}}))
|
||||
|
||||
try:
|
||||
(code, record, message, _nope) = modle_obj.import_data(
|
||||
fields, data, 'init', '', False,
|
||||
req.session.eval_context(req.context))
|
||||
except xmlrpclib.Fault, e:
|
||||
error = {"message": u"%s, %s" % (e.faultCode, e.faultString)}
|
||||
return '<script>window.top.%s(%s);</script>' % (
|
||||
jsonp, simplejson.dumps({'error':error}))
|
||||
|
||||
if code != -1:
|
||||
return '<script>window.top.%s(%s);</script>' % (
|
||||
jsonp, simplejson.dumps({'success':True}))
|
||||
|
||||
msg = u"Error during import: %s\n\nTrying to import record %r" % (
|
||||
message, record)
|
||||
return '<script>window.top.%s(%s);</script>' % (
|
||||
jsonp, simplejson.dumps({'error': {'message':msg}}))
|
||||
|
||||
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -26,8 +26,7 @@ Deferreds
|
|||
---------
|
||||
|
||||
Deferreds are a form of `promises`_. OpenERP Web currently uses
|
||||
`jQuery's deferred`_, but any `CommonJS Promises/A`_ implementation
|
||||
should work.
|
||||
`jQuery's deferred`_.
|
||||
|
||||
The core idea of deferreds is that potentially asynchronous methods
|
||||
will return a :js:class:`Deferred` object instead of an arbitrary
|
||||
|
@ -44,9 +43,8 @@ directly to asynchronous methods is the ability to :ref:`compose them
|
|||
Using deferreds
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
`CommonJS Promises/A`_ deferreds have only one method of importance:
|
||||
:js:func:`Deferred.then`. This method is used to attach new callbacks
|
||||
to the deferred object.
|
||||
Deferreds's most important method is :js:func:`Deferred.then`. It is
|
||||
used to attach new callbacks to the deferred object.
|
||||
|
||||
* the first parameter attaches a success callback, called when the
|
||||
deferred object is successfully resolved and provided with the
|
||||
|
@ -178,9 +176,9 @@ Deferred chaining
|
|||
|
||||
A second useful composition is starting an asynchronous operation as
|
||||
the result of an other asynchronous operation, and wanting the result
|
||||
of both: :js:func:`Deferred.then` returns the deferred on which it was
|
||||
called, so handle e.g. OpenERP's search/read sequence with this would
|
||||
require something along the lines of:
|
||||
of both: with the tools described so far, handling e.g. OpenERP's
|
||||
search/read sequence with this would require something along the lines
|
||||
of:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
|
@ -195,21 +193,14 @@ require something along the lines of:
|
|||
While it doesn't look too bad for trivial code, this quickly gets
|
||||
unwieldy.
|
||||
|
||||
Instead, jQuery provides a tool to handle this kind of chains:
|
||||
:js:func:`Deferred.pipe`.
|
||||
|
||||
:js:func:`~Deferred.pipe` has the same signature as
|
||||
:js:func:`~Deferred.then` and could be used in the same manner
|
||||
provided its return value was not used.
|
||||
|
||||
It differs from :js:func:`~Deferred.then` in two ways: it returns a
|
||||
new promise object, not the one it was called with, and the return
|
||||
values of the callbacks is actually important to it: whichever
|
||||
callback is called,
|
||||
But :js:func:`~Deferred.then` also allows handling this kind of
|
||||
chains: it returns a new promise object, not the one it was called
|
||||
with, and the return values of the callbacks is actually important to
|
||||
it: whichever callback is called,
|
||||
|
||||
* If the callback is not set (not provided or left to null), the
|
||||
resolution or rejection value(s) is simply forwarded to
|
||||
:js:func:`~Deferred.pipe`'s promise (it's essentially a noop)
|
||||
:js:func:`~Deferred.then`'s promise (it's essentially a noop)
|
||||
|
||||
* If the callback is set and does not return an observable object (a
|
||||
deferred or a promise), the value it returns (``undefined`` if it
|
||||
|
@ -217,7 +208,7 @@ callback is called,
|
|||
|
||||
.. code-block:: javascript
|
||||
|
||||
promise.pipe(function () {
|
||||
promise.then(function () {
|
||||
console.log('called');
|
||||
});
|
||||
|
||||
|
@ -234,7 +225,7 @@ callback is called,
|
|||
|
||||
.. code-block:: javascript
|
||||
|
||||
return Model.search(condition).pipe(function (ids) {
|
||||
return Model.search(condition).then(function (ids) {
|
||||
return Model.read(ids, fields);
|
||||
});
|
||||
|
||||
|
@ -243,108 +234,11 @@ callback is called,
|
|||
will be resolved with ``read``'s resolution values if the chain
|
||||
executes correctly.
|
||||
|
||||
:js:func:`~Deferred.pipe` is also useful to adapt third-party
|
||||
:js:func:`~Deferred.then` is also useful to adapt third-party
|
||||
promise-based APIs, in order to filter their resolution value counts
|
||||
for instance (to take advantage of :js:func:`when` 's special treatment
|
||||
of single-value promises).
|
||||
for instance (to take advantage of :js:func:`when` 's special
|
||||
treatment of single-value promises).
|
||||
|
||||
jQuery.Deferred API
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. js:function:: when(deferreds…)
|
||||
|
||||
:param deferreds: deferred objects to multiplex
|
||||
:returns: a multiplexed deferred
|
||||
:rtype: :js:class:`Deferred`
|
||||
|
||||
.. js:class:: Deferred
|
||||
|
||||
.. js:function:: Deferred.then(doneCallback[, failCallback])
|
||||
|
||||
Attaches new callbacks to the resolution or rejection of the
|
||||
deferred object. Callbacks are executed in the order they are
|
||||
attached to the deferred.
|
||||
|
||||
To provide only a failure callback, pass ``null`` as the
|
||||
``doneCallback``, to provide only a success callback the
|
||||
second argument can just be ignored (and not passed at all).
|
||||
|
||||
:param doneCallback: function called when the deferred is resolved
|
||||
:type doneCallback: Function
|
||||
:param failCallback: function called when the deferred is rejected
|
||||
:type failCallback: Function
|
||||
:returns: the deferred object on which it was called
|
||||
:rtype: :js:class:`Deferred`
|
||||
|
||||
.. js:function:: Deferred.done(doneCallback)
|
||||
|
||||
Attaches a new success callback to the deferred, shortcut for
|
||||
``deferred.then(doneCallback)``.
|
||||
|
||||
This is a jQuery extension to `CommonJS Promises/A`_ providing
|
||||
little value over calling :js:func:`~Deferred.then` directly,
|
||||
it should be avoided.
|
||||
|
||||
:param doneCallback: function called when the deferred is resolved
|
||||
:type doneCallback: Function
|
||||
:returns: the deferred object on which it was called
|
||||
:rtype: :js:class:`Deferred`
|
||||
|
||||
.. js:function:: Deferred.fail(failCallback)
|
||||
|
||||
Attaches a new failure callback to the deferred, shortcut for
|
||||
``deferred.then(null, failCallback)``.
|
||||
|
||||
A second jQuery extension to `Promises/A <CommonJS
|
||||
Promises/A>`_. Although it provides more value than
|
||||
:js:func:`~Deferred.done`, it still is not much and should be
|
||||
avoided as well.
|
||||
|
||||
:param failCallback: function called when the deferred is rejected
|
||||
:type failCallback: Function
|
||||
:returns: the deferred object on which it was called
|
||||
:rtype: :js:class:`Deferred`
|
||||
|
||||
.. js:function:: Deferred.promise()
|
||||
|
||||
Returns a read-only view of the deferred object, with all
|
||||
mutators (resolve and reject) methods removed.
|
||||
|
||||
.. js:function:: Deferred.resolve(value…)
|
||||
|
||||
Called to resolve a deferred, any value provided will be
|
||||
passed onto the success handlers of the deferred object.
|
||||
|
||||
Resolving a deferred which has already been resolved or
|
||||
rejected has no effect.
|
||||
|
||||
.. js:function:: Deferred.reject(value…)
|
||||
|
||||
Called to reject (fail) a deferred, any value provided will be
|
||||
passed onto the failure handler of the deferred object.
|
||||
|
||||
Rejecting a deferred which has already been resolved or
|
||||
rejected has no effect.
|
||||
|
||||
.. js:function:: Deferred.pipe(doneFilter[, failFilter])
|
||||
|
||||
Filters the result of a deferred, able to transform a success
|
||||
into failure and a failure into success, or to delay
|
||||
resolution further.
|
||||
|
||||
.. [#] or simply calling :js:class:`Deferred` as a function, the
|
||||
result is the same
|
||||
|
||||
.. [#] or not-promises, the `CommonJS Promises/B`_ role of
|
||||
:js:func:`when` is to be able to treat values and promises
|
||||
uniformly: :js:func:`when` will pass promises through directly,
|
||||
but non-promise values and objects will be transformed into a
|
||||
resolved promise (resolving themselves with the value itself).
|
||||
|
||||
jQuery's :js:func:`when` keeps this behavior making deferreds
|
||||
easy to build from "static" values, or allowing defensive code
|
||||
where expected promises are wrapped in :js:func:`when` just in
|
||||
case.
|
||||
|
||||
.. _promises: http://en.wikipedia.org/wiki/Promise_(programming)
|
||||
.. _jQuery's deferred: http://api.jquery.com/category/deferred-object/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.. highlight:: javascript
|
||||
|
||||
Creating a new client action
|
||||
============================
|
||||
Client actions
|
||||
==============
|
||||
|
||||
Client actions are the client-side version of OpenERP's "Server
|
||||
Actions": instead of allowing for semi-arbitrary code to be executed
|
|
@ -11,18 +11,19 @@ Contents:
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
changelog-7.0
|
||||
|
||||
presentation
|
||||
async
|
||||
rpc
|
||||
|
||||
widget
|
||||
search-view
|
||||
qweb
|
||||
rpc
|
||||
client_action
|
||||
form_view
|
||||
search_view
|
||||
list_view
|
||||
|
||||
list-view
|
||||
form-notes
|
||||
changelog-7.0
|
||||
|
||||
guides/client-action
|
||||
|
||||
testing
|
||||
|
||||
|
|
|
@ -451,7 +451,7 @@ formview, delegating instead to its
|
|||
created.
|
||||
|
||||
The result should be a valid form view, see :doc:`Form Notes
|
||||
<form-notes>` for various peculiarities of the form view
|
||||
<form_view>` for various peculiarities of the form view
|
||||
format.
|
||||
|
||||
:param editor: editor object asking for the view
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
Presentation
|
||||
============
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Prerequisites to code addons for the OpenERP Web Client:
|
||||
|
||||
- HTML5
|
||||
- CSS
|
||||
- Javascript (Ecmascript 5)
|
||||
- jQuery
|
||||
|
||||
Once you know all this, that's only the beginning. Most usages of Javascript/jQuery are small hacks to make a web page nicer. The OpenERP Client Web is different: it's a web application, not a web site. It doesn't have multiple pages generated by a server side code. Only one unique empty page is loaded and all the html is generated by Javascript code, the page is never reloaded. If you never developed that kind of application you still have lot of good practices to learn.
|
||||
|
||||
Generic Guidelines
|
||||
------------------
|
||||
|
||||
First, here are some generic recommandations about web 2.0 applications:
|
||||
|
||||
* **Do not use ids**. Html ids are evil, the key anti-feature that makes your components non-reusable. You want to identify a dom part? Save a jQuery object over that dom element. If you really need to use ids, use _.uniqueId(), but 99% of the time you don't need to, classes are sufficient.
|
||||
* **Do not use predictable css class names** like "content" or "navigation", ten other developers will have the same idea than you and there will be clashes. A simple way to avoid this is to use prefixes. For example, if you need a css class for the button named "new" that is contained in the form view which is itself contained in the OpenERP application, name it "oe-form-view-new-button".
|
||||
* **Do not use global selectors** like *$(".my-class")*, you never know if your component will be instantiated multiple times. Limit the selector with a context, like *$(".my-class", this.$el)*.
|
||||
* As a general advice, **Never assume you own the page**. When you create a component, it is never unique and is always surrounded by a bunch of crazy html. You have to do with it.
|
||||
* **Learn how to use jQuery's deferreds** [1]_. That concept may seem over-complicated, but the experience tell us that it is nearly impossible to create big-size javascript applications without that.
|
||||
|
||||
OpenERP guidelines
|
||||
------------------
|
||||
More recommendations related to the specific case of the OpenERP Web Client:
|
||||
|
||||
* The code should conform to EcmasScript 5 without the "use strict" mode as we support IE9.
|
||||
|
||||
* Your components should inherit from the *Widget* class. And use *Widget* 's methods (*appendTo*, *replace*,...) to insert your component and its content into the dom.
|
||||
|
||||
* Use QWeb templates for html rendering.
|
||||
|
||||
* All css classes should have the prefix *oe-* .
|
||||
|
||||
* Functions that call rpc() should return a deferred, even if it calls it indirectly. So a function that calls a function that calls a function that calls rpc() should return a deferred too.
|
||||
|
||||
.. [1] http://api.jquery.com/category/deferred-object/
|
|
@ -0,0 +1,79 @@
|
|||
|
||||
QWeb
|
||||
====
|
||||
|
||||
QWeb is the template engine used by the OpenERP Web Client. It is a home made engine create by OpenERP developers. There are a few things to note about it:
|
||||
|
||||
* Template are rendered in javascript on the client-side, the server does nothing.
|
||||
* It is an xml template engine, like Facelets_ for example. The source file must be a valid xml.
|
||||
* Templates are not interpreted. There are compiled to javascript. This makes them a lot faster to render, but sometimes harder to debug.
|
||||
* Most of the time it is used through the Widget class, but you can also use it directly using *openerp.web.qweb.render()* .
|
||||
|
||||
.. _Facelets: http://en.wikipedia.org/wiki/Facelets
|
||||
|
||||
Here is a typical QWeb file:
|
||||
|
||||
::
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates>
|
||||
<t t-name="Template1">
|
||||
<div>...</div>
|
||||
</t>
|
||||
<t t-name="Template2">
|
||||
<div>...</div>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
A QWeb file contains multiple templates, they are simply identified by a name.
|
||||
|
||||
Here is a sample QWeb template:
|
||||
|
||||
::
|
||||
|
||||
<t t-name="UserPage">
|
||||
<div>
|
||||
<p>Name: <t t-esc="widget.user_name"/></p>
|
||||
<p>Password: <input type="text" t-att-value="widget.password"/></p>
|
||||
<p t-if="widget.is_admin">This user is an Administrator</p>
|
||||
<t t-foreach="widget.roles" t-as="role">
|
||||
<p>User has role: <t t-esc="role"/></p>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
*widget* is a variable given to the template engine by Widget sub-classes when they decide to render their associated template, it is simply *this*. Here is the corresponding Widget sub-class:
|
||||
|
||||
::
|
||||
|
||||
UserPageWidget = openerp.base.Widget.extend({
|
||||
template: "UserPage",
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
this.user_name = "Xavier";
|
||||
this.password = "lilo";
|
||||
this.is_admin = true;
|
||||
this.roles = ["Web Developer", "IE Hater", "Steve Jobs Worshiper"];
|
||||
},
|
||||
});
|
||||
|
||||
It could output something like this:
|
||||
|
||||
::
|
||||
|
||||
<div>
|
||||
<p>Name: Xavier</p>
|
||||
<p>Password: <input type="text" value="lilo"/></p>
|
||||
<p>This user is an Administrator</p
|
||||
<p>User has role: Web Developer</p>
|
||||
<p>User has role: IE Hater</p>
|
||||
<p>User has role: Steve Jobs Worshiper</p>
|
||||
</div>
|
||||
|
||||
A QWeb template should always contain one unique root element to be used effectively with the Widget class, here it is a *<div>*. QWeb only react to *<t>* elements or attributes prefixed by *t-*. The *<t>* is simply a null element, it is only used when you need to use a *t-* attribute without outputting an html element at the same time. Here are the effects of the most common QWeb attributes:
|
||||
|
||||
* *t-esc* outputs the result of the evaluation of the given javascript expression
|
||||
* *t-att-ATTR* sets the value of the *ATTR* attribute to the result of the evaluation of the given javascript expression
|
||||
* *t-if* outputs the element and its content only if the given javascript expression returns true
|
||||
* *t-foreach* outputs as many times as contained in the list returned by the given javascript expression. For each iteration, a variable with the name defined by *t-as* contains the current element in the list.
|
|
@ -1,5 +1,5 @@
|
|||
User Interaction: Widget
|
||||
========================
|
||||
Widget
|
||||
======
|
||||
|
||||
This is the base class for all visual components. It corresponds to an MVC
|
||||
view. It provides a number of services to handle a section of a page:
|
||||
|
|
|
@ -11,6 +11,7 @@ import logging
|
|||
import mimetypes
|
||||
import os
|
||||
import pprint
|
||||
import random
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
|
@ -21,6 +22,7 @@ import urlparse
|
|||
import uuid
|
||||
import xmlrpclib
|
||||
|
||||
import babel.core
|
||||
import simplejson
|
||||
import werkzeug.contrib.sessions
|
||||
import werkzeug.datastructures
|
||||
|
@ -91,9 +93,25 @@ class WebRequest(object):
|
|||
self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex
|
||||
self.session = self.httpsession.get(self.session_id)
|
||||
if not self.session:
|
||||
self.httpsession[self.session_id] = self.session = session.OpenERPSession()
|
||||
self.session = session.OpenERPSession()
|
||||
self.httpsession[self.session_id] = self.session
|
||||
self.context = self.params.pop('context', None)
|
||||
self.debug = self.params.pop('debug', False) != False
|
||||
self.debug = self.params.pop('debug', False) is not False
|
||||
# Determine self.lang
|
||||
lang = self.params.get('lang', None)
|
||||
if lang is None:
|
||||
lang = self.session.eval_context(self.context).get('lang')
|
||||
if lang is None:
|
||||
lang = self.httprequest.cookies.get('lang')
|
||||
if lang is None:
|
||||
lang = self.httprequest.accept_languages.best
|
||||
if lang is None:
|
||||
lang = 'en_US'
|
||||
# tranform 2 letters lang like 'en' into 5 letters like 'en_US'
|
||||
lang = babel.core.LOCALE_ALIASES.get(lang, lang)
|
||||
# we use _ as seprator where RFC2616 uses '-'
|
||||
self.lang = lang.replace('-', '_')
|
||||
|
||||
|
||||
class JsonRequest(WebRequest):
|
||||
""" JSON-RPC2 over HTTP.
|
||||
|
@ -128,10 +146,9 @@ class JsonRequest(WebRequest):
|
|||
"id": null}
|
||||
|
||||
"""
|
||||
def dispatch(self, controller, method):
|
||||
def dispatch(self, method):
|
||||
""" Calls the method asked for by the JSON-RPC2 or JSONP request
|
||||
|
||||
:param controller: the instance of the controller which received the request
|
||||
:param method: the method which received the request
|
||||
|
||||
:returns: an utf8 encoded JSON-RPC2 or JSONP reply
|
||||
|
@ -170,9 +187,9 @@ class JsonRequest(WebRequest):
|
|||
self.jsonrequest = simplejson.loads(request, object_hook=nonliterals.non_literal_decoder)
|
||||
self.init(self.jsonrequest.get("params", {}))
|
||||
if _logger.isEnabledFor(logging.DEBUG):
|
||||
_logger.debug("--> %s.%s\n%s", controller.__class__.__name__, method.__name__, pprint.pformat(self.jsonrequest))
|
||||
_logger.debug("--> %s.%s\n%s", method.im_class.__name__, method.__name__, pprint.pformat(self.jsonrequest))
|
||||
response['id'] = self.jsonrequest.get('id')
|
||||
response["result"] = method(controller, self, **self.params)
|
||||
response["result"] = method(self, **self.params)
|
||||
except session.AuthenticationError:
|
||||
error = {
|
||||
'code': 100,
|
||||
|
@ -211,6 +228,10 @@ class JsonRequest(WebRequest):
|
|||
_logger.debug("<--\n%s", pprint.pformat(response))
|
||||
|
||||
if jsonp:
|
||||
# If we use jsonp, that's mean we are called from another host
|
||||
# Some browser (IE and Safari) do no allow third party cookies
|
||||
# We need then to manage http sessions manually.
|
||||
response['httpsessionid'] = self.httpsession.sid
|
||||
mime = 'application/javascript'
|
||||
body = "%s(%s);" % (jsonp, simplejson.dumps(response, cls=nonliterals.NonLiteralEncoder),)
|
||||
else:
|
||||
|
@ -230,16 +251,13 @@ def jsonrequest(f):
|
|||
the ``session_id``, ``context`` and ``debug`` keys (which are stripped out
|
||||
beforehand)
|
||||
"""
|
||||
@functools.wraps(f)
|
||||
def json_handler(controller, request):
|
||||
return JsonRequest(request).dispatch(controller, f)
|
||||
json_handler.exposed = True
|
||||
return json_handler
|
||||
f.exposed = 'json'
|
||||
return f
|
||||
|
||||
class HttpRequest(WebRequest):
|
||||
""" Regular GET/POST request
|
||||
"""
|
||||
def dispatch(self, controller, method):
|
||||
def dispatch(self, method):
|
||||
params = dict(self.httprequest.args)
|
||||
params.update(self.httprequest.form)
|
||||
params.update(self.httprequest.files)
|
||||
|
@ -250,9 +268,9 @@ class HttpRequest(WebRequest):
|
|||
akw[key] = value
|
||||
else:
|
||||
akw[key] = type(value)
|
||||
_logger.debug("%s --> %s.%s %r", self.httprequest.method, controller.__class__.__name__, method.__name__, akw)
|
||||
_logger.debug("%s --> %s.%s %r", self.httprequest.method, method.im_class.__name__, method.__name__, akw)
|
||||
try:
|
||||
r = method(controller, self, **self.params)
|
||||
r = method(self, **self.params)
|
||||
except xmlrpclib.Fault, e:
|
||||
r = werkzeug.exceptions.InternalServerError(cgi.escape(simplejson.dumps({
|
||||
'code': 200,
|
||||
|
@ -317,11 +335,8 @@ def httprequest(f):
|
|||
merged in the same dictionary), apart from the ``session_id``, ``context``
|
||||
and ``debug`` keys (which are stripped out beforehand)
|
||||
"""
|
||||
@functools.wraps(f)
|
||||
def http_handler(controller, request):
|
||||
return HttpRequest(request).dispatch(controller, f)
|
||||
http_handler.exposed = True
|
||||
return http_handler
|
||||
f.exposed = 'http'
|
||||
return f
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Controller registration with a metaclass
|
||||
|
@ -343,23 +358,13 @@ class Controller(object):
|
|||
#----------------------------------------------------------
|
||||
# Session context manager
|
||||
#----------------------------------------------------------
|
||||
STORES = {}
|
||||
|
||||
@contextlib.contextmanager
|
||||
def session_context(request, storage_path, session_cookie='httpsessionid'):
|
||||
session_store, session_lock = STORES.get(storage_path, (None, None))
|
||||
if not session_store:
|
||||
session_store = werkzeug.contrib.sessions.FilesystemSessionStore( storage_path)
|
||||
session_lock = threading.Lock()
|
||||
STORES[storage_path] = session_store, session_lock
|
||||
|
||||
sid = request.cookies.get(session_cookie)
|
||||
def session_context(request, session_store, session_lock, sid):
|
||||
with session_lock:
|
||||
if sid:
|
||||
request.session = session_store.get(sid)
|
||||
else:
|
||||
request.session = session_store.new()
|
||||
|
||||
try:
|
||||
yield request.session
|
||||
finally:
|
||||
|
@ -411,6 +416,18 @@ def session_context(request, storage_path, session_cookie='httpsessionid'):
|
|||
|
||||
session_store.save(request.session)
|
||||
|
||||
def session_gc(session_store):
|
||||
if random.random() < 0.001:
|
||||
# we keep session one week
|
||||
last_week = time.time() - 60*60*24*7
|
||||
for fname in os.listdir(session_store.path):
|
||||
path = os.path.join(session_store.path, fname)
|
||||
try:
|
||||
if os.path.getmtime(path) < last_week:
|
||||
os.unlink(path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
#----------------------------------------------------------
|
||||
# WSGI Application
|
||||
#----------------------------------------------------------
|
||||
|
@ -445,22 +462,23 @@ class Root(object):
|
|||
"""Root WSGI application for the OpenERP Web Client.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.httpsession_cookie = 'httpsessionid'
|
||||
self.addons = {}
|
||||
|
||||
static_dirs = self._load_addons()
|
||||
app = werkzeug.wsgi.SharedDataMiddleware( self.dispatch, static_dirs)
|
||||
self.dispatch = DisableCacheMiddleware(app)
|
||||
|
||||
# Setup http sessions
|
||||
try:
|
||||
username = getpass.getuser()
|
||||
except Exception:
|
||||
username = "unknown"
|
||||
self.session_storage = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username)
|
||||
|
||||
if not os.path.exists(self.session_storage):
|
||||
os.mkdir(self.session_storage, 0700)
|
||||
_logger.debug('HTTP sessions stored in: %s', self.session_storage)
|
||||
path = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username)
|
||||
if not os.path.exists(path):
|
||||
os.mkdir(path, 0700)
|
||||
self.session_store = werkzeug.contrib.sessions.FilesystemSessionStore(path)
|
||||
self.session_lock = threading.Lock()
|
||||
_logger.debug('HTTP sessions stored in: %s', path)
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
""" Handle a WSGI request
|
||||
|
@ -483,8 +501,14 @@ class Root(object):
|
|||
if not handler:
|
||||
response = werkzeug.exceptions.NotFound()
|
||||
else:
|
||||
with session_context(request, self.session_storage, self.httpsession_cookie) as session:
|
||||
result = handler( request)
|
||||
sid = request.cookies.get('sid')
|
||||
if not sid:
|
||||
sid = request.args.get('sid')
|
||||
|
||||
session_gc(self.session_store)
|
||||
|
||||
with session_context(request, self.session_store, self.session_lock, sid) as session:
|
||||
result = handler(request)
|
||||
|
||||
if isinstance(result, basestring):
|
||||
headers=[('Content-Type', 'text/html; charset=utf-8'), ('Content-Length', len(result))]
|
||||
|
@ -493,7 +517,7 @@ class Root(object):
|
|||
response = result
|
||||
|
||||
if hasattr(response, 'set_cookie'):
|
||||
response.set_cookie(self.httpsession_cookie, session.sid)
|
||||
response.set_cookie('sid', session.sid)
|
||||
|
||||
return response(environ, start_response)
|
||||
|
||||
|
@ -538,16 +562,21 @@ class Root(object):
|
|||
"""
|
||||
if l:
|
||||
ps = '/' + '/'.join(filter(None, l))
|
||||
meth = 'index'
|
||||
method_name = 'index'
|
||||
while ps:
|
||||
c = controllers_path.get(ps)
|
||||
if c:
|
||||
m = getattr(c, meth, None)
|
||||
if m and getattr(m, 'exposed', False):
|
||||
_logger.debug("Dispatching to %s %s %s", ps, c, meth)
|
||||
return m
|
||||
ps, _slash, meth = ps.rpartition('/')
|
||||
if not ps and meth:
|
||||
method = getattr(c, method_name, None)
|
||||
if method:
|
||||
exposed = getattr(method, 'exposed', False)
|
||||
if exposed == 'json':
|
||||
_logger.debug("Dispatch json to %s %s %s", ps, c, method_name)
|
||||
return lambda request: JsonRequest(request).dispatch(method)
|
||||
elif exposed == 'http':
|
||||
_logger.debug("Dispatch http to %s %s %s", ps, c, method_name)
|
||||
return lambda request: HttpRequest(request).dispatch(method)
|
||||
ps, _slash, method_name = ps.rpartition('/')
|
||||
if not ps and method_name:
|
||||
ps = '/'
|
||||
return None
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:07+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:07+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:07+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:07+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
"X-Poedit-Language: Czech\n"
|
||||
|
||||
#. openerp-web
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
"Language: es\n"
|
||||
|
||||
#. openerp-web
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:07+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-08-24 09:16+0000\n"
|
||||
"Last-Translator: Herczeg Péter <herczegp@gmail.com>\n"
|
||||
"PO-Revision-Date: 2012-10-26 12:17+0000\n"
|
||||
"Last-Translator: Herczeg Péter <hp@erp-cloud.hu>\n"
|
||||
"Language-Team: Hungarian <hu@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
@ -755,7 +755,7 @@ msgstr "Választani kell legalább egy rekordot!"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:875
|
||||
msgid "Uploading..."
|
||||
msgstr ""
|
||||
msgstr "Feltöltés"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:885
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-02-16 21:49+0000\n"
|
||||
"Last-Translator: Davide Corio - agilebg.com <davide.corio@agilebg.com>\n"
|
||||
"PO-Revision-Date: 2012-10-22 14:36+0000\n"
|
||||
"Last-Translator: Marius Marolla <mariusmarolla@areablu.net>\n"
|
||||
"Language-Team: Italian <it@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
@ -129,56 +129,56 @@ msgstr "OpenERP - Unsupported/Community Version"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:619
|
||||
msgid "less than a minute ago"
|
||||
msgstr ""
|
||||
msgstr "meno di un minuto fa"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:620
|
||||
msgid "about a minute ago"
|
||||
msgstr ""
|
||||
msgstr "circa un minuto fa"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:621
|
||||
#, python-format
|
||||
msgid "%d minutes ago"
|
||||
msgstr ""
|
||||
msgstr "%d minuti fa"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:622
|
||||
msgid "about an hour ago"
|
||||
msgstr ""
|
||||
msgstr "circa un'ora fa"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:623
|
||||
#, python-format
|
||||
msgid "%d hours ago"
|
||||
msgstr ""
|
||||
msgstr "%d ore fa"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:624
|
||||
msgid "a day ago"
|
||||
msgstr ""
|
||||
msgstr "un giorno fa"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:625
|
||||
#, python-format
|
||||
msgid "%d days ago"
|
||||
msgstr ""
|
||||
msgstr "%d giorni fa"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:626
|
||||
msgid "about a month ago"
|
||||
msgstr ""
|
||||
msgstr "circa un mese fa"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:627
|
||||
#, python-format
|
||||
msgid "%d months ago"
|
||||
msgstr ""
|
||||
msgstr "%d mesi fa"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:628
|
||||
msgid "about a year ago"
|
||||
msgstr ""
|
||||
msgstr "circa un anno fa"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:629
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
@ -124,7 +124,7 @@ msgstr "За Нас"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:1052
|
||||
msgid "OpenERP - Unsupported/Community Version"
|
||||
msgstr "Versão da Comunidade / Sem suporte oficial da OpenERP S/A"
|
||||
msgstr "OpenERP - Неподдржана/На заедницата Верзија"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:619
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
@ -243,17 +243,19 @@ msgid ""
|
|||
"Destination fields should only be selected once, some fields are selected "
|
||||
"more than once:"
|
||||
msgstr ""
|
||||
"Pola docelowe muszą być wybierane tylko raz. niektóre inne pola mogą być "
|
||||
"wybierane więcej niż raz:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/data_import.js:386
|
||||
msgid "*Required Fields are not selected :"
|
||||
msgstr ""
|
||||
msgstr "*Wymagane pola nie zostały wybrane :"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/formats.js:139
|
||||
#, python-format
|
||||
msgid "(%d records)"
|
||||
msgstr ""
|
||||
msgstr "(%d rekordów)"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/formats.js:325
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -15,8 +15,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
@ -485,7 +485,7 @@ msgstr "Doriti intr-adevar sa eliminati aceasta vizualizare?"
|
|||
#: addons/web/static/src/js/view_editor.js:364
|
||||
#, python-format
|
||||
msgid "View Editor %d - %s"
|
||||
msgstr "Editor Vizualizare %d - %s"
|
||||
msgstr "Vezi Editor %d - %s"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_editor.js:367
|
||||
|
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-02-20 07:27+0000\n"
|
||||
"Last-Translator: Aleksei Motsik <Unknown>\n"
|
||||
"PO-Revision-Date: 2012-11-01 12:07+0000\n"
|
||||
"Last-Translator: Chertykov Denis <chertykov@gmail.com>\n"
|
||||
"Language-Team: Russian <ru@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
@ -129,62 +129,62 @@ msgstr "OpenERP - Не поддерживаемая/Community Версия"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:619
|
||||
msgid "less than a minute ago"
|
||||
msgstr ""
|
||||
msgstr "меньше минуты назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:620
|
||||
msgid "about a minute ago"
|
||||
msgstr ""
|
||||
msgstr "примерно минуту назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:621
|
||||
#, python-format
|
||||
msgid "%d minutes ago"
|
||||
msgstr ""
|
||||
msgstr "%d минут назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:622
|
||||
msgid "about an hour ago"
|
||||
msgstr ""
|
||||
msgstr "примерно час назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:623
|
||||
#, python-format
|
||||
msgid "%d hours ago"
|
||||
msgstr ""
|
||||
msgstr "%d часов назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:624
|
||||
msgid "a day ago"
|
||||
msgstr ""
|
||||
msgstr "день назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:625
|
||||
#, python-format
|
||||
msgid "%d days ago"
|
||||
msgstr ""
|
||||
msgstr "%d дней назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:626
|
||||
msgid "about a month ago"
|
||||
msgstr ""
|
||||
msgstr "примерно месяц назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:627
|
||||
#, python-format
|
||||
msgid "%d months ago"
|
||||
msgstr ""
|
||||
msgstr "%d месяцев/месяца назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:628
|
||||
msgid "about a year ago"
|
||||
msgstr ""
|
||||
msgstr "примерно год назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:629
|
||||
#, python-format
|
||||
msgid "%d years ago"
|
||||
msgstr ""
|
||||
msgstr "%d лет назад"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/data_export.js:6
|
||||
|
@ -290,29 +290,29 @@ msgstr ""
|
|||
#: addons/web/static/src/js/search.js:948
|
||||
#, python-format
|
||||
msgid "Filter on: %s"
|
||||
msgstr ""
|
||||
msgstr "Фильтр по: %s"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:999
|
||||
msgid "Filter"
|
||||
msgstr ""
|
||||
msgstr "Фильтр"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:1108
|
||||
#, python-format
|
||||
msgid "Group by: %s"
|
||||
msgstr ""
|
||||
msgstr "Группировать по: %s"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:1132
|
||||
msgid "GroupBy"
|
||||
msgstr ""
|
||||
msgstr "Группировать по"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:1267
|
||||
#, python-format
|
||||
msgid "Search %(field)s for: %(value)s"
|
||||
msgstr ""
|
||||
msgstr "Искать %(field)s для: %(value)s"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:869
|
||||
|
@ -339,7 +339,7 @@ msgstr "Нет"
|
|||
#: addons/web/static/src/js/search.js:1416
|
||||
#, python-format
|
||||
msgid "Search %(field)s at: %(value)s"
|
||||
msgstr ""
|
||||
msgstr "Искать %(field)s в: %(value)s"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1286
|
||||
|
@ -349,13 +349,13 @@ msgstr "Фильтры"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:1762
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
msgstr "Расширенный"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:1853
|
||||
#, python-format
|
||||
msgid "%(field)s %(operator)s \"%(value)s\""
|
||||
msgstr ""
|
||||
msgstr "%(field)s %(operator)s \"%(value)s\""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:1341
|
||||
|
@ -535,7 +535,7 @@ msgstr "Удалить"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:762
|
||||
msgid "Duplicate"
|
||||
msgstr "Клонировать"
|
||||
msgstr "Дублировать"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_form.js:133
|
||||
|
@ -633,12 +633,12 @@ msgstr "Добавить: "
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_form.js:4230
|
||||
msgid "Save As..."
|
||||
msgstr ""
|
||||
msgstr "Сохранить как..."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_form.js:4230
|
||||
msgid "The field is empty, there's nothing to save !"
|
||||
msgstr ""
|
||||
msgstr "Поле пусто, нечего сохранять !"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_list.js:8
|
||||
|
@ -680,7 +680,7 @@ msgstr "Внимание"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_list.js:716
|
||||
msgid "You must select at least one record."
|
||||
msgstr ""
|
||||
msgstr "Вы должны выбрать хотя бы одну запись ."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_list.js:1243
|
||||
|
@ -728,17 +728,17 @@ msgstr "Не удалось найти определение текущего
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:716
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
msgstr "Печать"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:717
|
||||
msgid "Attachment"
|
||||
msgstr ""
|
||||
msgstr "Вложение"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:718 addons/web/static/src/xml/base.xml:276
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
msgstr "Еще"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:810
|
||||
|
@ -758,12 +758,12 @@ msgstr "Вы должны выбрать хотя бы одну запись."
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:875
|
||||
msgid "Uploading..."
|
||||
msgstr ""
|
||||
msgstr "Загрузка..."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:885
|
||||
msgid "Do you really want to delete this attachment ?"
|
||||
msgstr ""
|
||||
msgstr "Вы действительно хотите удалить это вложение?"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:962
|
||||
|
@ -867,13 +867,13 @@ msgstr "Удалить"
|
|||
#: addons/web/static/src/xml/base.xml:166
|
||||
#: addons/web/static/src/xml/base.xml:329
|
||||
msgid "Backup"
|
||||
msgstr "Резервное копирование"
|
||||
msgstr "Резервная копия"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:195
|
||||
#: addons/web/static/src/xml/base.xml:330
|
||||
msgid "Restore"
|
||||
msgstr "Востановить"
|
||||
msgstr "Восстановить"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:332
|
||||
|
@ -908,12 +908,12 @@ msgstr "Язык по умолчанию:"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:91
|
||||
msgid "Admin password:"
|
||||
msgstr "Пароль Администратора:"
|
||||
msgstr "Пароль администратора:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:95
|
||||
msgid "Confirm password:"
|
||||
msgstr "Подтверждение пароля:"
|
||||
msgstr "Подтвердите пароль:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:109
|
||||
|
@ -960,17 +960,17 @@ msgstr "Подтвердить мастер-пароль:"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:325
|
||||
msgid "About OpenERP"
|
||||
msgstr ""
|
||||
msgstr "Об OpenERP"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:327
|
||||
msgid "Log out"
|
||||
msgstr ""
|
||||
msgstr "Выход"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:333
|
||||
msgid "Activate the developer mode"
|
||||
msgstr ""
|
||||
msgstr "Включить режим разработчика"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1820
|
||||
|
@ -1030,12 +1030,12 @@ msgstr "Пароль ещё раз:"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:390
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
msgstr "Открыть"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:390
|
||||
msgid "ERP"
|
||||
msgstr ""
|
||||
msgstr "ERP"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:477
|
||||
|
@ -1050,7 +1050,7 @@ msgstr "Просмотр Лога (доступ на чтение)"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:450
|
||||
msgid "Toggle Form Layout Outline"
|
||||
msgstr ""
|
||||
msgstr "Переключить структуры макета формы"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:479
|
||||
|
@ -1080,7 +1080,7 @@ msgstr "Изменить действие"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:486
|
||||
msgid "Edit Workflow"
|
||||
msgstr "Редактировать Процесс"
|
||||
msgstr "Редактировать процесс"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:491
|
||||
|
@ -1115,28 +1115,28 @@ msgstr "Дата изменения:"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:518
|
||||
msgid "Delete this attachment"
|
||||
msgstr ""
|
||||
msgstr "Удалить вложение"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:523
|
||||
msgid "/web/binary/upload_attachment"
|
||||
msgstr ""
|
||||
msgstr "/web/binary/upload_attachment"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:527
|
||||
msgid "Add..."
|
||||
msgstr ""
|
||||
msgstr "Добавить..."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:622
|
||||
#: addons/web/static/src/xml/base.xml:687
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
msgstr "или"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:687
|
||||
msgid "Discard"
|
||||
msgstr ""
|
||||
msgstr "Отменить"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:806
|
||||
|
@ -1222,7 +1222,7 @@ msgstr "При изменении:"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:981
|
||||
msgid "Relation:"
|
||||
msgstr "Отношение:"
|
||||
msgstr "Связь:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:985
|
||||
|
@ -1242,13 +1242,13 @@ msgstr "Выбрать дату"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:948
|
||||
msgid "Open Resource"
|
||||
msgstr ""
|
||||
msgstr "Открыть ресурс"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1162
|
||||
#: addons/web/static/src/xml/base.xml:1205
|
||||
msgid "Set Image"
|
||||
msgstr "Назначить изображение"
|
||||
msgstr "Установить изображение"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_form.js:1623
|
||||
|
@ -1263,12 +1263,12 @@ msgstr "Очистить"
|
|||
#: addons/web/static/src/xml/base.xml:1179
|
||||
#: addons/web/static/src/xml/base.xml:1230
|
||||
msgid "Uploading ..."
|
||||
msgstr "Загружаю ..."
|
||||
msgstr "Загружается ..."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1066
|
||||
msgid "width: 83px;"
|
||||
msgstr ""
|
||||
msgstr "ширина: 83px ;"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1207
|
||||
|
@ -1320,7 +1320,7 @@ msgstr "Поле"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1205
|
||||
msgid "Advanced Search..."
|
||||
msgstr ""
|
||||
msgstr "Расширенный поиск..."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1287
|
||||
|
@ -1355,22 +1355,22 @@ msgstr "(Имеющийся фильтр с таким же имененем б
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1376
|
||||
msgid "Custom Filters"
|
||||
msgstr ""
|
||||
msgstr "Настраиваемые фильтры"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1379
|
||||
msgid "Save current filter"
|
||||
msgstr ""
|
||||
msgstr "Сохранить текущий фильтр"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1381
|
||||
msgid "Filter name"
|
||||
msgstr ""
|
||||
msgstr "Название фильтра"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1383
|
||||
msgid "Share with all users"
|
||||
msgstr ""
|
||||
msgstr "Совместно со всеми пользователями"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:298
|
||||
|
@ -1381,42 +1381,42 @@ msgstr "Добавить на Панель"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1394
|
||||
msgid "Title of new Dashboard item"
|
||||
msgstr ""
|
||||
msgstr "Название нового элемента панели"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1395
|
||||
msgid "save"
|
||||
msgstr ""
|
||||
msgstr "сохранить"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1399
|
||||
msgid "Select Dashboard to add this filter to"
|
||||
msgstr ""
|
||||
msgstr "Выберите панель, чтобы добавить этот фильтр"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1406
|
||||
msgid "Advanced Search"
|
||||
msgstr ""
|
||||
msgstr "Расширенный поиск"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1411
|
||||
msgid "Add a condition"
|
||||
msgstr ""
|
||||
msgstr "Добавить условие"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1412
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
msgstr "Применить"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1509
|
||||
msgid "Save & New"
|
||||
msgstr "Сохранить и Создать"
|
||||
msgstr "Сохранить и создать"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1510
|
||||
msgid "Save & Close"
|
||||
msgstr "Сохранить и Закрыть"
|
||||
msgstr "Сохранить и закрыть"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1617
|
||||
|
@ -1426,9 +1426,9 @@ msgid ""
|
|||
" You can export all data or only the fields that can be "
|
||||
"reimported after modification."
|
||||
msgstr ""
|
||||
"Этот мастер экспортирует все найденные данные в CSV файл.\n"
|
||||
" Вы можете экспортровать все данные либо только те поля которые "
|
||||
"могут быть в последствии импортированны."
|
||||
"Этот мастер экспортирует все найденные данные в CSV-файл.\n"
|
||||
" Вы можете экспортировать все данные, либо только те поля которые "
|
||||
"должны быть в последствии импортированы после изменений."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1624
|
||||
|
@ -1556,13 +1556,13 @@ msgid ""
|
|||
"For use if CSV files have titles on multiple lines, skips more than a single "
|
||||
"line during import"
|
||||
msgstr ""
|
||||
"Применимо если в CSV файле заголовки расположены в нескольких строках и из "
|
||||
"Применимо если в CSV файле заголовки расположены в нескольких строках и их "
|
||||
"необходимо пропустить"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1713
|
||||
msgid "--- Don't Import ---"
|
||||
msgstr ""
|
||||
msgstr "--- Не импортировать ---"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1809
|
||||
|
@ -1669,9 +1669,6 @@ msgstr "Предпросмотр файла, который система не
|
|||
#~ msgid "Activate the developper mode"
|
||||
#~ msgstr "Активировать режим разработчика"
|
||||
|
||||
#~ msgid "Notebook Page \""
|
||||
#~ msgstr "Страница Блокнота \""
|
||||
|
||||
#~ msgid "Filter disabled due to invalid syntax"
|
||||
#~ msgstr "Фильтр отключен из-за неверного синтаксиса"
|
||||
|
||||
|
@ -1686,3 +1683,6 @@ msgstr "Предпросмотр файла, который система не
|
|||
|
||||
#~ msgid "Advanced Filters"
|
||||
#~ msgstr "Расширенные фильтры"
|
||||
|
||||
#~ msgid "Notebook Page \""
|
||||
#~ msgstr "Страница блокнота \""
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-01-31 06:25+0000\n"
|
||||
"Last-Translator: ERP Basing <erp@basing.si>\n"
|
||||
"PO-Revision-Date: 2012-11-01 16:38+0000\n"
|
||||
"Last-Translator: Dusan Laznik <laznik@mentis.si>\n"
|
||||
"Language-Team: Slovenian <sl@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
@ -129,62 +129,62 @@ msgstr "OpenERP-Community Version"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:619
|
||||
msgid "less than a minute ago"
|
||||
msgstr ""
|
||||
msgstr "manj kot minuto nazaj"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:620
|
||||
msgid "about a minute ago"
|
||||
msgstr ""
|
||||
msgstr "približno pred minuto"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:621
|
||||
#, python-format
|
||||
msgid "%d minutes ago"
|
||||
msgstr ""
|
||||
msgstr "pred %d minutami"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:622
|
||||
msgid "about an hour ago"
|
||||
msgstr ""
|
||||
msgstr "pred približno eno uro"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:623
|
||||
#, python-format
|
||||
msgid "%d hours ago"
|
||||
msgstr ""
|
||||
msgstr "Pred %d urami"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:624
|
||||
msgid "a day ago"
|
||||
msgstr ""
|
||||
msgstr "pred enim dnevom"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:625
|
||||
#, python-format
|
||||
msgid "%d days ago"
|
||||
msgstr ""
|
||||
msgstr "pred %d dnevi"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:626
|
||||
msgid "about a month ago"
|
||||
msgstr ""
|
||||
msgstr "približno pred enim mesecem"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:627
|
||||
#, python-format
|
||||
msgid "%d months ago"
|
||||
msgstr ""
|
||||
msgstr "pred %d meseci"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:628
|
||||
msgid "about a year ago"
|
||||
msgstr ""
|
||||
msgstr "približno pred enim letom"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:629
|
||||
#, python-format
|
||||
msgid "%d years ago"
|
||||
msgstr ""
|
||||
msgstr "Pred %d leti"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/data_export.js:6
|
||||
|
@ -293,13 +293,13 @@ msgstr ""
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:999
|
||||
msgid "Filter"
|
||||
msgstr ""
|
||||
msgstr "Filter:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:1108
|
||||
#, python-format
|
||||
msgid "Group by: %s"
|
||||
msgstr ""
|
||||
msgstr "Združi po: %s"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:1132
|
||||
|
@ -347,7 +347,7 @@ msgstr "Filtri"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:1762
|
||||
msgid "Advanced"
|
||||
msgstr ""
|
||||
msgstr "Napredeno"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/search.js:1853
|
||||
|
@ -632,7 +632,7 @@ msgstr "Dodaj: "
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_form.js:4230
|
||||
msgid "Save As..."
|
||||
msgstr ""
|
||||
msgstr "Shrani kot ..."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_form.js:4230
|
||||
|
@ -669,7 +669,7 @@ msgstr "Skupina"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_list.js:549
|
||||
msgid "Do you really want to remove these records?"
|
||||
msgstr ""
|
||||
msgstr "Res želite odstraniti te zapise?"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:925
|
||||
|
@ -679,7 +679,7 @@ msgstr "Opozorilo"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_list.js:716
|
||||
msgid "You must select at least one record."
|
||||
msgstr ""
|
||||
msgstr "Izbrati morate vsaj en zapis"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/view_list.js:1243
|
||||
|
@ -727,17 +727,17 @@ msgstr ""
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:716
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
msgstr "Tiskanje"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:717
|
||||
msgid "Attachment"
|
||||
msgstr ""
|
||||
msgstr "Priponka"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:718 addons/web/static/src/xml/base.xml:276
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
msgstr "Dodatno"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:810
|
||||
|
@ -757,7 +757,7 @@ msgstr "Izbrati morate vsaj en zapis."
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:875
|
||||
msgid "Uploading..."
|
||||
msgstr ""
|
||||
msgstr "Pošiljanje ..."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/views.js:885
|
||||
|
@ -963,7 +963,7 @@ msgstr ""
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:327
|
||||
msgid "Log out"
|
||||
msgstr ""
|
||||
msgstr "Odjava"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:333
|
||||
|
@ -1028,7 +1028,7 @@ msgstr "Potrditev gesla:"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:390
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
msgstr "Odpri"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:390
|
||||
|
@ -1123,18 +1123,18 @@ msgstr ""
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:527
|
||||
msgid "Add..."
|
||||
msgstr ""
|
||||
msgstr "Dodaj ..."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:622
|
||||
#: addons/web/static/src/xml/base.xml:687
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
msgstr "ali"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:687
|
||||
msgid "Discard"
|
||||
msgstr ""
|
||||
msgstr "Opusti"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:806
|
||||
|
@ -1220,7 +1220,7 @@ msgstr ""
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:981
|
||||
msgid "Relation:"
|
||||
msgstr ""
|
||||
msgstr "Relacija:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:985
|
||||
|
@ -1235,7 +1235,7 @@ msgstr "Odpri vir"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1063
|
||||
msgid "Select date"
|
||||
msgstr ""
|
||||
msgstr "Izberi datum"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:948
|
||||
|
@ -1298,7 +1298,7 @@ msgstr ""
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1260
|
||||
msgid "Button Type:"
|
||||
msgstr ""
|
||||
msgstr "Vrsta tipke:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1264
|
||||
|
@ -1318,7 +1318,7 @@ msgstr "Polje"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1205
|
||||
msgid "Advanced Search..."
|
||||
msgstr ""
|
||||
msgstr "Napredno iskanje ..."
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1287
|
||||
|
@ -1363,7 +1363,7 @@ msgstr ""
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1381
|
||||
msgid "Filter name"
|
||||
msgstr ""
|
||||
msgstr "Ime filtra"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/xml/base.xml:1383
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:07+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-02-17 07:29+0000\n"
|
||||
"Last-Translator: Jeff Wang <wjfonhand@hotmail.com>\n"
|
||||
"PO-Revision-Date: 2012-11-06 04:40+0000\n"
|
||||
"Last-Translator: Wei \"oldrev\" Li <oldrev@gmail.com>\n"
|
||||
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
@ -129,56 +129,56 @@ msgstr "OpenERP社区支持版"
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:619
|
||||
msgid "less than a minute ago"
|
||||
msgstr ""
|
||||
msgstr "一分钟内"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:620
|
||||
msgid "about a minute ago"
|
||||
msgstr ""
|
||||
msgstr "大约一分钟"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:621
|
||||
#, python-format
|
||||
msgid "%d minutes ago"
|
||||
msgstr ""
|
||||
msgstr "%d 分钟之前"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:622
|
||||
msgid "about an hour ago"
|
||||
msgstr ""
|
||||
msgstr "大约一小时前"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:623
|
||||
#, python-format
|
||||
msgid "%d hours ago"
|
||||
msgstr ""
|
||||
msgstr "%d 小时前"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:624
|
||||
msgid "a day ago"
|
||||
msgstr ""
|
||||
msgstr "一天前"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:625
|
||||
#, python-format
|
||||
msgid "%d days ago"
|
||||
msgstr ""
|
||||
msgstr "%d 天前"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:626
|
||||
msgid "about a month ago"
|
||||
msgstr ""
|
||||
msgstr "大约一月前"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:627
|
||||
#, python-format
|
||||
msgid "%d months ago"
|
||||
msgstr ""
|
||||
msgstr "%d 月前"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:628
|
||||
msgid "about a year ago"
|
||||
msgstr ""
|
||||
msgstr "大约一年前"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/coresetup.js:629
|
||||
|
@ -247,13 +247,13 @@ msgstr ""
|
|||
#. openerp-web
|
||||
#: addons/web/static/src/js/data_import.js:386
|
||||
msgid "*Required Fields are not selected :"
|
||||
msgstr ""
|
||||
msgstr "*没有选择必须的字段:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/formats.js:139
|
||||
#, python-format
|
||||
msgid "(%d records)"
|
||||
msgstr ""
|
||||
msgstr "(%d 条记录)"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/formats.js:325
|
||||
|
|
|
@ -14,8 +14,8 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-13 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16137)\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-15 05:08+0000\n"
|
||||
"X-Generator: Launchpad (build 16265)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web/static/src/js/chrome.js:176
|
||||
|
|
|
@ -295,7 +295,12 @@
|
|||
|
||||
// Bind the window resize event when the width or height is auto or %
|
||||
if (/auto|%/.test("" + options.width + options.height))
|
||||
$(window).resize(function() {refresh(editor);});
|
||||
$(window).resize(function() {
|
||||
// CHM Note MonkeyPatch: if the DOM is not remove, refresh the cleditor
|
||||
if(editor.$main.parent().parent().size()) {
|
||||
refresh(editor);
|
||||
}
|
||||
});
|
||||
|
||||
// Create the iframe and resize the controls
|
||||
refresh(editor);
|
||||
|
@ -562,7 +567,7 @@
|
|||
//==================
|
||||
// Private Functions
|
||||
//==================
|
||||
|
||||
|
||||
// checksum - returns a checksum using the Adler-32 method
|
||||
function checksum(text)
|
||||
{
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
Copyright 2011 Xavier Morel. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are
|
||||
permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
of conditions and the following disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY XAVIER MOREL ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,59 +0,0 @@
|
|||
.. -*- restructuredtext -*-
|
||||
|
||||
In jQuery 1.5, jQuery has introduced a Deferred object in order to
|
||||
better handle callbacks.
|
||||
|
||||
Along with Deferred, it introduced ``jQuery.when`` which allows, among
|
||||
other things, for multiplexing deferreds (waiting on multiple
|
||||
deferreds at the same time).
|
||||
|
||||
While this is very nice if all deferreds are available at the same
|
||||
point, it doesn't really work if the resolution of a deferred can
|
||||
generate more deferreds, or for collections of deferreds coming from
|
||||
multiple sources (which may not be aware of one another).
|
||||
|
||||
Deferred.queue tries to be a solution to this. It is based on the
|
||||
principle of FIFO multiple-producers multiple-consumers tasks queues,
|
||||
such as Python's `queue.Queue`_. Any code with a reference to the
|
||||
queue can add a promise to the queue, and the queue (which is a
|
||||
promise itself) will only be resolved once all promises within are
|
||||
resolved.
|
||||
|
||||
Quickstart
|
||||
----------
|
||||
|
||||
Deferred.queue has a very simple life cycle: it is dormant when
|
||||
created, it starts working as soon as promises get added to it (via
|
||||
``.push``, or by providing them directly to its constructor), and as
|
||||
soon as the last promise in the queue is resolved it resolves itself.
|
||||
|
||||
If any promise in the queue fails, the queue itself will be rejected
|
||||
(without waiting for further promises).
|
||||
|
||||
Once a queue has been resolved or rejected, adding new promises to it
|
||||
results in an error.
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
``jQuery.Deferred.queue([promises...])``
|
||||
Creates a new deferred queue. Can be primed with a series of promise
|
||||
objects.
|
||||
|
||||
``.push(promise...)``
|
||||
Adds promises to the queue. Returns the queue itself (can be
|
||||
chained).
|
||||
|
||||
If the queue has already been resolved or rejected, raises an error.
|
||||
|
||||
``.then([doneCallbacks][, failCallbacks])``
|
||||
Promise/A ``then`` method.
|
||||
|
||||
``.done(doneCallbacks)``
|
||||
jQuery ``done`` extension to promise objects
|
||||
|
||||
``.fail(failCallbacks)``
|
||||
jQuery ``fail`` extension to promise objects
|
||||
|
||||
.. _queue.Queue:
|
||||
http://docs.python.org/dev/library/queue.html
|
|
@ -1,34 +0,0 @@
|
|||
(function ($) {
|
||||
"use strict";
|
||||
$.extend($.Deferred, {
|
||||
queue: function () {
|
||||
var queueDeferred = $.Deferred();
|
||||
var promises = 0;
|
||||
|
||||
function resolve() {
|
||||
if (--promises > 0) {
|
||||
return;
|
||||
}
|
||||
setTimeout($.proxy(queueDeferred, 'resolve'), 0);
|
||||
}
|
||||
|
||||
var promise = $.extend(queueDeferred.promise(), {
|
||||
push: function () {
|
||||
if (this.isResolved() || this.isRejected()) {
|
||||
throw new Error("Can not add promises to a resolved "
|
||||
+ "or rejected promise queue");
|
||||
}
|
||||
|
||||
promises += 1;
|
||||
$.when.apply(null, arguments).then(
|
||||
resolve, $.proxy(queueDeferred, 'reject'));
|
||||
return this;
|
||||
}
|
||||
});
|
||||
if (arguments.length) {
|
||||
promise.push.apply(promise, arguments);
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
});
|
||||
})(jQuery)
|
|
@ -27,7 +27,8 @@
|
|||
var $tip = this.tip();
|
||||
|
||||
$tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
|
||||
$tip[0].className = 'tipsy openerp oe_tooltip '; // reset classname in case of dynamic gravity
|
||||
$tip[0].className = 'tipsy '; // reset classname in case of dynamic gravity
|
||||
$tip.openerpClass('oe_tooltip');
|
||||
$tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);
|
||||
|
||||
var pos = $.extend({}, this.$element.offset(), {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#jQuery UI Bootstrap
|
||||
|
||||
##Summary
|
||||
|
||||
This is a project I started to bring the beauty of Twitter's Bootstrap to jQuery UI widgets.
|
||||
|
||||
Twitter's Bootstrap was one of my favorite projects to come out of 2011, but having used it regularly it left me wanting two things:
|
||||
|
||||
* The ability to work side-by-side with jQuery UI (something which caused a number of widgets to break visually)
|
||||
* The ability to theme jQuery UI widgets using Bootstrap styles. Whilst I love jQuery UI, I (like others) find some of the current themes to look a little dated. My hope is that this theme provides a decent alternative for others that feel the same.
|
||||
|
||||
To clarify, this project doesn't aim or intend to replace Twitter Bootstrap. It merely provides a jQuery UI-compatible theme inspired by Bootstrap's design. It also provides a version of Bootstrap CSS with a few (minor) sections commented out which enable the theme to work along-side it.
|
||||
|
||||
I welcome any and all feedback as I'd very much like this theme to be as solid as possible.
|
||||
|
||||
##Browser-support
|
||||
|
||||
All modern browsers are targeted by this theme with 'lo-res' experiences (i.e no gradients, border-radius etc.) provided for users using older browsers.
|
||||
|
||||
There *are* some minor known issues lingering that I'm working on, but the hope is that in time those will all get ironed out.
|
||||
|
||||
##jQuery UI support
|
||||
|
||||
This theme targets jQuery UI 1.8.16 and the default version of jQuery included in the (current) jQuery UI builds (jQuery 1.6.2). I'm aware of jQuery 1.7.1 and intend on upgrading anything necessary in the theme to use it when the jQuery UI team officially include it in their theme packs.
|
||||
|
||||
|
||||
##Demo
|
||||
|
||||
For a live preview of the theme, see [http://addyosmani.github.com/jquery-ui-bootstrap](http://addyosmani.github.com/jquery-ui-bootstrap).
|
||||
|
||||
A [blog post](http://addyosmani.com/blog/jquery-ui-bootstrap/) with some more details about the project is also available.
|
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-bg_flat_0_aaaaaa_40x100.png
Executable file → Normal file
Before Width: | Height: | Size: 180 B After Width: | Height: | Size: 180 B |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-bg_glass_55_fbf9ee_1x400.png
Executable file → Normal file
Before Width: | Height: | Size: 120 B After Width: | Height: | Size: 120 B |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-bg_glass_65_ffffff_1x400.png
Executable file → Normal file
Before Width: | Height: | Size: 105 B After Width: | Height: | Size: 105 B |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-bg_glass_75_dadada_1x400.png
Executable file → Normal file
Before Width: | Height: | Size: 111 B After Width: | Height: | Size: 111 B |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-bg_glass_75_e6e6e6_1x400.png
Executable file → Normal file
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 110 B |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-bg_glass_75_ffffff_1x400.png
Executable file → Normal file
Before Width: | Height: | Size: 107 B After Width: | Height: | Size: 107 B |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png
Executable file → Normal file
Before Width: | Height: | Size: 101 B After Width: | Height: | Size: 101 B |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-bg_inset-soft_95_fef1ec_1x100.png
Executable file → Normal file
Before Width: | Height: | Size: 123 B After Width: | Height: | Size: 123 B |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-icons_222222_256x240.png
Executable file → Normal file
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-icons_2e83ff_256x240.png
Executable file → Normal file
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-icons_454545_256x240.png
Executable file → Normal file
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-icons_888888_256x240.png
Executable file → Normal file
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
0
addons/web/static/lib/jquery.ui.bootstrap/css/custom-theme/images/ui-icons_cd0a0a_256x240.png
Executable file → Normal file
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
@ -23,6 +23,7 @@
|
|||
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
|
||||
|
||||
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-disabled { cursor: default !important; }
|
||||
|
@ -59,7 +60,7 @@
|
|||
----------------------------------*/
|
||||
.ui-widget { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size:13px; }
|
||||
.ui-widget .ui-widget { font-size: 1em; }
|
||||
/*.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1em; }*/
|
||||
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1em; }
|
||||
.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_75_ffffff_1x400.png) 50% 50% repeat-x; color: #404040; }
|
||||
.ui-widget-content a { color: #404040; }
|
||||
.ui-widget-header {
|
||||
|
@ -399,7 +400,6 @@
|
|||
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
|
||||
|
||||
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
|
||||
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
|
||||
|
@ -432,9 +432,9 @@
|
|||
*/
|
||||
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
||||
/*
|
||||
* jQuery UI Accordion 1.8.16
|
||||
* jQuery UI Accordion 1.9.0
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
|
@ -445,7 +445,7 @@
|
|||
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; font-weight:bold; }
|
||||
.ui-accordion .ui-accordion-li-fix { display: inline; }
|
||||
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
|
||||
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
|
||||
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 1.7em; }
|
||||
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
|
||||
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
||||
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
|
||||
|
@ -465,46 +465,55 @@
|
|||
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
||||
|
||||
/*
|
||||
* jQuery UI Menu 1.8.16
|
||||
* jQuery UI Menu 1.9.0
|
||||
*
|
||||
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Copyright 2012-10-11, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Menu#theming
|
||||
*/
|
||||
.ui-menu {
|
||||
list-style:none;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
display:block;
|
||||
float: left;
|
||||
}
|
||||
.ui-menu .ui-menu {
|
||||
margin-top: -3px;
|
||||
}
|
||||
.ui-menu .ui-menu-item {
|
||||
margin:0;
|
||||
padding: 0;
|
||||
zoom: 1;
|
||||
float: left;
|
||||
clear: left;
|
||||
width: 100%;
|
||||
}
|
||||
.ui-menu .ui-menu-item a {
|
||||
text-decoration:none;
|
||||
display:block;
|
||||
padding:.2em .4em;
|
||||
line-height:1.5;
|
||||
zoom:1;
|
||||
}
|
||||
.ui-menu .ui-menu-item a.ui-state-hover,
|
||||
.ui-menu .ui-menu-item a.ui-state-active {
|
||||
font-weight: normal;
|
||||
background:#0064CD;
|
||||
color:#fff
|
||||
|
||||
.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; float:left; outline: none; }
|
||||
.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
|
||||
.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1;float: left;clear: left; width: 100%; }
|
||||
.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
|
||||
.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
|
||||
.ui-menu .ui-menu-item a.ui-state-focus,
|
||||
.ui-menu .ui-menu-item a.ui-state-active {
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
color: #ffffff;
|
||||
background: #0064cd;
|
||||
background-color: #0064cd;
|
||||
background-repeat: repeat-x;
|
||||
background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
|
||||
background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
|
||||
background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
|
||||
background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
|
||||
background-image: -o-linear-gradient(top, #049cdb, #0064cd);
|
||||
background-image: linear-gradient(top, #049cdb, #0064cd);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
border-color: #0064cd #0064cd #003f81;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
|
||||
.ui-menu .ui-state-disabled a { cursor: default; }
|
||||
|
||||
/* icon support */
|
||||
.ui-menu-icons { position: relative; }
|
||||
.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
|
||||
|
||||
/* left-aligned */
|
||||
.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
|
||||
|
||||
/* right-aligned */
|
||||
.ui-menu .ui-menu-icon { position: static; float: right; }
|
||||
|
||||
.ui-menu { width: 200px; margin-bottom: 2em; }
|
||||
|
||||
/*
|
||||
* jQuery UI Button 1.8.16
|
||||
|
@ -651,7 +660,31 @@ button.ui-button-icons-only { width: 3.7em; }
|
|||
/* workarounds */
|
||||
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
||||
|
||||
/*
|
||||
* jQuery UI spinner 1.9.0
|
||||
*
|
||||
* Copyright 2012-10-11, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Menu#theming
|
||||
*/
|
||||
|
||||
.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
|
||||
.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
|
||||
.ui-spinner{}
|
||||
.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; z-index: 100; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
|
||||
.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
|
||||
.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
|
||||
.ui-spinner-up { top: 0; }
|
||||
.ui-spinner-down { bottom: 0; }
|
||||
|
||||
/* TR overrides */
|
||||
span.ui-spinner { background: none; }
|
||||
.ui-spinner .ui-icon-triangle-1-s {
|
||||
/* need to fix icons sprite */
|
||||
background-position:-65px -16px;
|
||||
}
|
||||
|
||||
/*
|
||||
* jQuery UI Dialog 1.8.16
|
||||
|
@ -805,14 +838,16 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
|
|||
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
||||
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
||||
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
||||
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
|
||||
* jQuery UI Tabs 1.8.16
|
||||
.ui-slider-vertical .ui-slider-range-max { top: 0; }
|
||||
|
||||
/*
|
||||
* jQuery UI Tabs 1.9.0
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Tabs#theming
|
||||
* http://jqueryui.com/tabs/
|
||||
*/
|
||||
.ui-tabs .ui-tabs-nav{ background:none; border-color: #ddd;
|
||||
border-style: solid;
|
||||
|
@ -824,14 +859,11 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
|
|||
background:whiteSmoke;
|
||||
border-bottom:1px solid #ddd;
|
||||
padding-bottom:0px;
|
||||
color:#4c4c4c;
|
||||
color:#00438A;
|
||||
}
|
||||
|
||||
|
||||
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; border-bottom:1px solid #DDD; }
|
||||
.ui-tabs .ui-tabs-nav li { text-decoration: none; list-style: none; float: left; position: relative; top: 1px; padding: 0px 0px 1px 0px; white-space: nowrap; background:none; border:0px;
|
||||
|
||||
}
|
||||
.ui-tabs .ui-tabs-nav li { text-decoration: none; list-style: none; float: left; position: relative; top: 1px; padding: 0px 0px 1px 0px; white-space: nowrap; background:none; border:0px; }
|
||||
|
||||
.ui-tabs-nav .ui-state-default{
|
||||
-webkit-box-shadow: 0px 0px 0px #ffffff; /* Saf3-4, iOS 4.0.2 - 4.2, Android 2.3+ */
|
||||
|
@ -853,25 +885,24 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
|
|||
|
||||
|
||||
}
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 0px; outline:none;}
|
||||
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a {
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: 0; padding-bottom: 0px; outline:none;}
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a {
|
||||
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #ddd;
|
||||
border-bottom-color: #ffffff;
|
||||
cursor: default;
|
||||
color:#4c4c4c;
|
||||
color:gray;
|
||||
outline:none;
|
||||
}
|
||||
|
||||
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-selected:hover{
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active:hover{
|
||||
background:#ffffff;
|
||||
outline:none;
|
||||
}
|
||||
|
||||
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; color:#0069D6; background:none; font-weight:normal; margin-bottom:-1px;}
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
|
||||
.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; color:#0069D6; background:none; font-weight:normal; margin-bottom:-1px;}
|
||||
/* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
||||
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
||||
.ui-tabs-panel .ui-button{text-decoration:none;}
|
||||
|
@ -883,16 +914,39 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
|
|||
filter:none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* jQuery UI Datepicker 1.8.16
|
||||
* jQuery UI Tooltip 1.9.0
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Copyright 2012-10-11, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Datepicker#theming
|
||||
* http://jqueryui.com/tooltip/
|
||||
*/
|
||||
.ui-tooltip {
|
||||
padding:8px;
|
||||
position:absolute;
|
||||
z-index:9999;
|
||||
-o-box-shadow: 0 0 5px #ddd;
|
||||
-moz-box-shadow: 0 0 5px #ddd;
|
||||
-webkit-box-shadow: 0 0 5px #ddd;
|
||||
/*box-shadow: 0 2px 5px #ddd;*/
|
||||
box-shadow: inset 0 1px 0 #ffffff;
|
||||
}
|
||||
/* Fades and background-images don't work well together in IE6, drop the image */
|
||||
* html .ui-tooltip {
|
||||
background-image: none;
|
||||
}
|
||||
body .ui-tooltip { border-width:2px; }
|
||||
|
||||
/*
|
||||
* jQuery UI Datepicker 1.9.0
|
||||
*
|
||||
* Copyright 2012-10-11, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://jqueryui.com/datepicker/
|
||||
*/
|
||||
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
||||
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; border:0px; font-weight: bold; width: 100%; padding: 4px 0; background-color: #f5f5f5; color: #808080; }
|
||||
|
@ -982,7 +1036,7 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
|
|||
}
|
||||
|
||||
.ui-datepicker td:hover{
|
||||
color:white;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.ui-datepicker td .ui-state-default {
|
||||
|
@ -1001,21 +1055,34 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
|
|||
margin-bottom:0px;
|
||||
font-size:normal;
|
||||
text-shadow: 0px;
|
||||
color:white;
|
||||
color: #ffffff;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.ui-datepicker td .ui-state-default:hover{
|
||||
background:#0064cd;
|
||||
color:white;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
.ui-datepicker td .ui-state-hover {
|
||||
color: #ffffff;
|
||||
background: #0064cd;
|
||||
background-color: #0064cd;
|
||||
background-repeat: repeat-x;
|
||||
background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
|
||||
background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
|
||||
background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
|
||||
background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
|
||||
background-image: -o-linear-gradient(top, #049cdb, #0064cd);
|
||||
background-image: linear-gradient(top, #049cdb, #0064cd);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
border-color: #0064cd #0064cd #003f81;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-khtml-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* jQuery UI Progressbar 1.8.16
|
||||
*
|
||||
|
@ -1048,7 +1115,7 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
|
|||
|
||||
|
||||
/*** Input field styling from Bootstrap **/
|
||||
input, textarea {
|
||||
/* input, textarea {
|
||||
-webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
|
||||
-moz-transition: border linear 0.2s, box-shadow linear 0.2s;
|
||||
-ms-transition: border linear 0.2s, box-shadow linear 0.2s;
|
||||
|
@ -1065,7 +1132,7 @@ input:focus, textarea:focus {
|
|||
-moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
|
||||
}
|
||||
/*input[type=file]:focus, input[type=checkbox]:focus, select:focus {
|
||||
input[type=file]:focus, input[type=checkbox]:focus, select:focus {
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
|
@ -1073,8 +1140,9 @@ input:focus, textarea:focus {
|
|||
}*/
|
||||
|
||||
/*input[type="text"],
|
||||
input[type="password"],
|
||||
textarea,*/
|
||||
input[type="password"],*/
|
||||
.ui-autocomplete-input,
|
||||
/*textarea,*/
|
||||
.uneditable-input {
|
||||
display: inline-block;
|
||||
padding: 4px;
|
|
@ -1,5 +1,15 @@
|
|||
|
||||
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-left, .ui-corner-bottom{ border-radius:0px;}
|
||||
/*
|
||||
* jQuery UI Tabs 1.9.0
|
||||
*
|
||||
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://jqueryui.com/tabs/
|
||||
*/
|
||||
|
||||
.ui-state-active,.ui-tabs-selected { border-radius:0px;}
|
||||
.ui-tabs-selected { border-radius:0px;}
|
||||
.ui-tabs .ui-tabs-nav li{ filter:none;}
|
Before Width: | Height: | Size: 120 B After Width: | Height: | Size: 144 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.2 KiB |
|
@ -1,12 +1,8 @@
|
|||
/*
|
||||
* jQuery UI CSS Framework 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Theming/API
|
||||
*/
|
||||
/*! jQuery UI - v1.9.1 - 2012-10-29
|
||||
* http://jqueryui.com
|
||||
* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
|
||||
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
|
||||
* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */
|
||||
|
||||
/* Layout helpers
|
||||
----------------------------------*/
|
||||
|
@ -36,20 +32,198 @@
|
|||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
||||
.ui-resizable { position: relative;}
|
||||
.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
|
||||
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
||||
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
||||
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
||||
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
||||
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
||||
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
||||
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
||||
.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }
|
||||
.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }
|
||||
.ui-accordion .ui-accordion-noicons { padding-left: .7em; }
|
||||
.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }
|
||||
.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
||||
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }
|
||||
.ui-autocomplete {
|
||||
position: absolute;
|
||||
top: 0; /* #8656 */
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* workarounds */
|
||||
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
||||
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
|
||||
.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; }
|
||||
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
|
||||
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
|
||||
.ui-button-icons-only { width: 3.4em; }
|
||||
button.ui-button-icons-only { width: 3.7em; }
|
||||
|
||||
/*
|
||||
* jQuery UI CSS Framework 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Theming/API
|
||||
*
|
||||
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
|
||||
*/
|
||||
/*button text element */
|
||||
.ui-button .ui-button-text { display: block; line-height: 1.4; }
|
||||
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
|
||||
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
|
||||
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
|
||||
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
|
||||
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
|
||||
/* no icon support for input elements, provide padding by default */
|
||||
input.ui-button { padding: .4em 1em; }
|
||||
|
||||
/*button icon element(s) */
|
||||
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
|
||||
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
|
||||
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
|
||||
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
||||
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
||||
|
||||
/*button sets*/
|
||||
.ui-buttonset { margin-right: 7px; }
|
||||
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
|
||||
|
||||
/* workarounds */
|
||||
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
||||
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
||||
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
||||
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
||||
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
||||
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
||||
.ui-datepicker .ui-datepicker-next { right:2px; }
|
||||
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
||||
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
||||
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
||||
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
||||
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
||||
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
||||
.ui-datepicker select.ui-datepicker-month,
|
||||
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
||||
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
||||
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
||||
.ui-datepicker td { border: 0; padding: 1px; }
|
||||
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
||||
|
||||
/* with multiple calendars */
|
||||
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
||||
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
||||
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
||||
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
||||
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
||||
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
||||
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
||||
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
||||
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
||||
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
||||
|
||||
/* RTL support */
|
||||
.ui-datepicker-rtl { direction: rtl; }
|
||||
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||
|
||||
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
||||
.ui-datepicker-cover {
|
||||
position: absolute; /*must have*/
|
||||
z-index: -1; /*must have*/
|
||||
filter: mask(); /*must have*/
|
||||
top: -4px; /*must have*/
|
||||
left: -4px; /*must have*/
|
||||
width: 200px; /*must have*/
|
||||
height: 200px; /*must have*/
|
||||
}.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
|
||||
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
|
||||
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
|
||||
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
|
||||
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
||||
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
||||
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
|
||||
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
|
||||
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
||||
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
||||
.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
|
||||
.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
|
||||
.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; }
|
||||
.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
|
||||
.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
|
||||
.ui-menu .ui-menu-item a.ui-state-focus,
|
||||
.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; }
|
||||
|
||||
.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
|
||||
.ui-menu .ui-state-disabled a { cursor: default; }
|
||||
|
||||
/* icon support */
|
||||
.ui-menu-icons { position: relative; }
|
||||
.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
|
||||
|
||||
/* left-aligned */
|
||||
.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
|
||||
|
||||
/* right-aligned */
|
||||
.ui-menu .ui-menu-icon { position: static; float: right; }
|
||||
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
|
||||
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }.ui-slider { position: relative; text-align: left; }
|
||||
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
||||
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
|
||||
|
||||
.ui-slider-horizontal { height: .8em; }
|
||||
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
||||
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
||||
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
||||
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
||||
|
||||
.ui-slider-vertical { width: .8em; height: 100px; }
|
||||
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
||||
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
||||
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
||||
.ui-slider-vertical .ui-slider-range-max { top: 0; }.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
|
||||
.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
|
||||
.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
|
||||
.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
|
||||
.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
|
||||
.ui-spinner-up { top: 0; }
|
||||
.ui-spinner-down { bottom: 0; }
|
||||
|
||||
/* TR overrides */
|
||||
.ui-spinner .ui-icon-triangle-1-s {
|
||||
/* need to fix icons sprite */
|
||||
background-position:-65px -16px;
|
||||
}
|
||||
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
||||
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
|
||||
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0; padding: 0; white-space: nowrap; }
|
||||
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
|
||||
.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
||||
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
||||
.ui-tooltip {
|
||||
padding: 8px;
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
max-width: 300px;
|
||||
-webkit-box-shadow: 0 0 5px #aaa;
|
||||
box-shadow: 0 0 5px #aaa;
|
||||
}
|
||||
/* Fades and background-images don't work well together in IE6, drop the image */
|
||||
* html .ui-tooltip {
|
||||
background-image: none;
|
||||
}
|
||||
body .ui-tooltip { border-width: 2px; }
|
||||
|
||||
/* Component containers
|
||||
----------------------------------*/
|
||||
|
@ -66,10 +240,9 @@
|
|||
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
|
||||
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
|
||||
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
|
||||
.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
|
||||
.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121; text-decoration: none; }
|
||||
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
|
||||
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
|
||||
.ui-widget :active { outline: none; }
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
|
@ -81,6 +254,7 @@
|
|||
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
|
||||
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
|
||||
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
|
||||
.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
|
||||
|
||||
/* Icons
|
||||
----------------------------------*/
|
||||
|
@ -222,8 +396,8 @@
|
|||
.ui-icon-help { background-position: -48px -144px; }
|
||||
.ui-icon-check { background-position: -64px -144px; }
|
||||
.ui-icon-bullet { background-position: -80px -144px; }
|
||||
.ui-icon-radio-off { background-position: -96px -144px; }
|
||||
.ui-icon-radio-on { background-position: -112px -144px; }
|
||||
.ui-icon-radio-on { background-position: -96px -144px; }
|
||||
.ui-icon-radio-off { background-position: -112px -144px; }
|
||||
.ui-icon-pin-w { background-position: -128px -144px; }
|
||||
.ui-icon-pin-s { background-position: -144px -144px; }
|
||||
.ui-icon-play { background-position: 0 -160px; }
|
||||
|
@ -283,283 +457,5 @@
|
|||
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
|
||||
|
||||
/* Overlays */
|
||||
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
|
||||
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
|
||||
* jQuery UI Resizable 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Resizable#theming
|
||||
*/
|
||||
.ui-resizable { position: relative;}
|
||||
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
|
||||
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
|
||||
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
|
||||
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
|
||||
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
|
||||
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
|
||||
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
|
||||
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
|
||||
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
|
||||
* jQuery UI Selectable 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Selectable#theming
|
||||
*/
|
||||
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
|
||||
/*
|
||||
* jQuery UI Accordion 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Accordion#theming
|
||||
*/
|
||||
/* IE/Win - Fix animation bug - #4615 */
|
||||
.ui-accordion { width: 100%; }
|
||||
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
|
||||
.ui-accordion .ui-accordion-li-fix { display: inline; }
|
||||
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
|
||||
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
|
||||
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
|
||||
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
|
||||
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
|
||||
.ui-accordion .ui-accordion-content-active { display: block; }
|
||||
/*
|
||||
* jQuery UI Autocomplete 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Autocomplete#theming
|
||||
*/
|
||||
.ui-autocomplete { position: absolute; cursor: default; }
|
||||
|
||||
/* workarounds */
|
||||
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
|
||||
|
||||
/*
|
||||
* jQuery UI Menu 1.8.17
|
||||
*
|
||||
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Menu#theming
|
||||
*/
|
||||
.ui-menu {
|
||||
list-style:none;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
display:block;
|
||||
float: left;
|
||||
}
|
||||
.ui-menu .ui-menu {
|
||||
margin-top: -3px;
|
||||
}
|
||||
.ui-menu .ui-menu-item {
|
||||
margin:0;
|
||||
padding: 0;
|
||||
zoom: 1;
|
||||
float: left;
|
||||
clear: left;
|
||||
width: 100%;
|
||||
}
|
||||
.ui-menu .ui-menu-item a {
|
||||
text-decoration:none;
|
||||
display:block;
|
||||
padding:.2em .4em;
|
||||
line-height:1.5;
|
||||
zoom:1;
|
||||
}
|
||||
.ui-menu .ui-menu-item a.ui-state-hover,
|
||||
.ui-menu .ui-menu-item a.ui-state-active {
|
||||
font-weight: normal;
|
||||
margin: -1px;
|
||||
}
|
||||
/*
|
||||
* jQuery UI Button 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Button#theming
|
||||
*/
|
||||
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
|
||||
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
|
||||
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
|
||||
.ui-button-icons-only { width: 3.4em; }
|
||||
button.ui-button-icons-only { width: 3.7em; }
|
||||
|
||||
/*button text element */
|
||||
.ui-button .ui-button-text { display: block; line-height: 1.4; }
|
||||
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
|
||||
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
|
||||
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
|
||||
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
|
||||
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
|
||||
/* no icon support for input elements, provide padding by default */
|
||||
input.ui-button { padding: .4em 1em; }
|
||||
|
||||
/*button icon element(s) */
|
||||
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
|
||||
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
|
||||
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
|
||||
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
||||
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
|
||||
|
||||
/*button sets*/
|
||||
.ui-buttonset { margin-right: 7px; }
|
||||
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
|
||||
|
||||
/* workarounds */
|
||||
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
|
||||
/*
|
||||
* jQuery UI Dialog 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Dialog#theming
|
||||
*/
|
||||
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
|
||||
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
|
||||
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
|
||||
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
|
||||
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
|
||||
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
|
||||
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
|
||||
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
|
||||
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
|
||||
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
|
||||
.ui-draggable .ui-dialog-titlebar { cursor: move; }
|
||||
/*
|
||||
* jQuery UI Slider 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Slider#theming
|
||||
*/
|
||||
.ui-slider { position: relative; text-align: left; }
|
||||
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
|
||||
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
|
||||
|
||||
.ui-slider-horizontal { height: .8em; }
|
||||
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
|
||||
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
|
||||
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
|
||||
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
|
||||
|
||||
.ui-slider-vertical { width: .8em; height: 100px; }
|
||||
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
|
||||
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
|
||||
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
|
||||
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
|
||||
* jQuery UI Tabs 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Tabs#theming
|
||||
*/
|
||||
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
||||
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
|
||||
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
|
||||
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
|
||||
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
||||
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
|
||||
.ui-tabs .ui-tabs-hide { display: none !important; }
|
||||
/*
|
||||
* jQuery UI Datepicker 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Datepicker#theming
|
||||
*/
|
||||
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
|
||||
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
|
||||
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
|
||||
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
|
||||
.ui-datepicker .ui-datepicker-prev { left:2px; }
|
||||
.ui-datepicker .ui-datepicker-next { right:2px; }
|
||||
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
|
||||
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
|
||||
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
|
||||
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
|
||||
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
|
||||
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
|
||||
.ui-datepicker select.ui-datepicker-month,
|
||||
.ui-datepicker select.ui-datepicker-year { width: 49%;}
|
||||
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
|
||||
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
|
||||
.ui-datepicker td { border: 0; padding: 1px; }
|
||||
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
|
||||
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
|
||||
|
||||
/* with multiple calendars */
|
||||
.ui-datepicker.ui-datepicker-multi { width:auto; }
|
||||
.ui-datepicker-multi .ui-datepicker-group { float:left; }
|
||||
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
|
||||
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
|
||||
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
|
||||
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
|
||||
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
|
||||
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
|
||||
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
|
||||
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
|
||||
|
||||
/* RTL support */
|
||||
.ui-datepicker-rtl { direction: rtl; }
|
||||
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
|
||||
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
|
||||
|
||||
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
|
||||
.ui-datepicker-cover {
|
||||
display: none; /*sorry for IE5*/
|
||||
display/**/: block; /*sorry for IE5*/
|
||||
position: absolute; /*must have*/
|
||||
z-index: -1; /*must have*/
|
||||
filter: mask(); /*must have*/
|
||||
top: -4px; /*must have*/
|
||||
left: -4px; /*must have*/
|
||||
width: 200px; /*must have*/
|
||||
height: 200px; /*must have*/
|
||||
}/*
|
||||
* jQuery UI Progressbar 1.8.17
|
||||
*
|
||||
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://docs.jquery.com/UI/Progressbar#theming
|
||||
*/
|
||||
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
|
||||
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
|
||||
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); }
|
||||
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
|
5
addons/web/static/lib/jquery.ui/css/smoothness/jquery-ui-1.9.1.custom.min.css
vendored
Normal file
|
@ -20,21 +20,6 @@
|
|||
font-style: normal;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.oe_topbar, .oe_leftbar, .oe_loading {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.openerp.openerp_webclient_container {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text-tag .text-button {
|
||||
height: auto !important;
|
||||
min-height: 16px;
|
||||
}
|
||||
|
||||
.openerp {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
@ -47,6 +32,9 @@
|
|||
* http://stackoverflow.com/questions/2855589/replace-input-type-file-by-an-image
|
||||
*/
|
||||
}
|
||||
.openerp.openerp_webclient_container {
|
||||
height: 100%;
|
||||
}
|
||||
.openerp :-moz-placeholder {
|
||||
color: #afafb6 !important;
|
||||
font-style: italic !important;
|
||||
|
@ -198,6 +186,13 @@
|
|||
.openerp .oe_bounce_container {
|
||||
display: inline-block;
|
||||
}
|
||||
.openerp .text-tag .text-button {
|
||||
height: auto !important;
|
||||
min-height: 16px;
|
||||
}
|
||||
.openerp .ui-tabs {
|
||||
position: static;
|
||||
}
|
||||
.openerp.ui-dialog {
|
||||
display: none;
|
||||
padding: 6px;
|
||||
|
@ -215,7 +210,7 @@
|
|||
background-clip: padding-box;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-content {
|
||||
padding: 0px;
|
||||
padding: 0;
|
||||
}
|
||||
.openerp.ui-dialog .ui-dialog-titlebar, .openerp.ui-dialog .ui-dialog-content, .openerp.ui-dialog .ui-dialog-buttonpane {
|
||||
padding: 16px;
|
||||
|
@ -657,7 +652,7 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
.openerp .oe_dropdown_toggle {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
font-weight: normal;
|
||||
}
|
||||
.openerp .oe_dropdown_hover:hover .oe_dropdown_menu, .openerp .oe_dropdown_menu.oe_opened {
|
||||
|
@ -1134,6 +1129,7 @@
|
|||
height: 40px;
|
||||
width: 157px;
|
||||
margin: 14px 0;
|
||||
border: 0;
|
||||
}
|
||||
.openerp .oe_footer {
|
||||
position: fixed;
|
||||
|
@ -1928,6 +1924,9 @@
|
|||
min-height: 327px;
|
||||
margin-left: -15px;
|
||||
}
|
||||
.openerp .oe_view.oe_cannot_create .oe_view_nocontent_create {
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_formview {
|
||||
background: white;
|
||||
}
|
||||
|
@ -2055,10 +2054,11 @@
|
|||
padding-bottom: 0;
|
||||
}
|
||||
.openerp .oe_form div.oe_chatter {
|
||||
min-width: 650px;
|
||||
max-width: 860px;
|
||||
box-sizing: border-box;
|
||||
min-width: 682px;
|
||||
max-width: 892px;
|
||||
margin: 0 auto;
|
||||
padding: 16px 0 48px;
|
||||
padding: 16px 16px 48px;
|
||||
}
|
||||
.openerp .oe_form div.oe_form_configuration p, .openerp .oe_form div.oe_form_configuration ul, .openerp .oe_form div.oe_form_configuration ol {
|
||||
color: #aaaaaa;
|
||||
|
@ -2300,16 +2300,16 @@
|
|||
text-align: justify;
|
||||
}
|
||||
.openerp .oe_form_editable .oe_form .oe_form_field_integer input {
|
||||
width: 6em !important;
|
||||
width: 6em;
|
||||
}
|
||||
.openerp .oe_form_editable .oe_form .oe_form_field_float input {
|
||||
width: 7em !important;
|
||||
width: 7em;
|
||||
}
|
||||
.openerp .oe_form_editable .oe_form .oe_form_field_date input {
|
||||
width: 7.5em !important;
|
||||
width: 7.5em;
|
||||
}
|
||||
.openerp .oe_form_editable .oe_form .oe_form_field_datetime input {
|
||||
width: 11.5em !important;
|
||||
width: 11.5em;
|
||||
}
|
||||
.openerp .oe_hidden_input_file {
|
||||
position: relative;
|
||||
|
@ -2355,6 +2355,77 @@
|
|||
.openerp .oe_form .oe_form_field_image:hover .oe_form_field_image_controls {
|
||||
display: block;
|
||||
}
|
||||
.openerp .oe_fileupload {
|
||||
display: inline-block;
|
||||
clear: both;
|
||||
width: 100%;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_add {
|
||||
float: left;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
left: 2px;
|
||||
top: 7px;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_add button {
|
||||
display: inline;
|
||||
height: 24px;
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_add button.oe_attach {
|
||||
width: 24px;
|
||||
overflow: hidden;
|
||||
width: 24px;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
color: #7c7bad;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
text-shadow: none;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_add button.oe_attach .oe_e {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
left: -9px;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_add input.oe_form_binary_file {
|
||||
display: inline-block;
|
||||
margin-left: -5px;
|
||||
height: 28px;
|
||||
width: 52px;
|
||||
margin-top: -26px;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_add .oe_attach_label {
|
||||
color: #7c7bad;
|
||||
margin-left: -3px;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_attachments {
|
||||
margin-bottom: 4px;
|
||||
margin-right: 0px;
|
||||
font-size: 12px;
|
||||
border-radius: 2px;
|
||||
border: solid 1px rgba(124, 123, 173, 0.14);
|
||||
}
|
||||
.openerp .oe_fileupload .oe_attachments .oe_attachment {
|
||||
padding: 2px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_attachments .oe_attachment .oe_e {
|
||||
font-size: 23px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_attachments .oe_attachment .oe_e:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_attachments .oe_attachment:nth-child(odd) {
|
||||
background: white;
|
||||
}
|
||||
.openerp .oe_fileupload .oe_attachments .oe_attachment:nth-child(even) {
|
||||
background: #f4f5fa;
|
||||
}
|
||||
.openerp .oe_form_field_many2one td:first-child {
|
||||
position: relative;
|
||||
}
|
||||
|
@ -2368,6 +2439,9 @@
|
|||
float: right;
|
||||
padding-left: 2px;
|
||||
}
|
||||
.openerp .oe_form_field_many2one input {
|
||||
padding-right: 13px;
|
||||
}
|
||||
.openerp.ui-autocomplete li.oe_m2o_dropdown_option a {
|
||||
font-style: italic;
|
||||
padding-left: 2em;
|
||||
|
@ -2513,6 +2587,9 @@
|
|||
.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_view_manager .oe_view_manager_view_list, .openerp .oe_form_field_many2many > .oe_view_manager .oe_view_manager_view_list {
|
||||
min-height: 132px;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
|
@ -2556,13 +2633,11 @@
|
|||
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;
|
||||
padding: 4px 6px 3px;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) {
|
||||
color: transparent;
|
||||
text-shadow: none;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) * {
|
||||
visibility: hidden;
|
||||
|
@ -2571,32 +2646,33 @@
|
|||
top: 5px;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_m2o_cm_button {
|
||||
display: none;
|
||||
line-height: 19px;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_input_icon {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field {
|
||||
min-width: 0;
|
||||
max-width: none;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field textarea {
|
||||
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 {
|
||||
-moz-border-radius: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
border: 1px solid #aaaaff;
|
||||
margin: 0;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field textarea, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field select {
|
||||
min-width: 0;
|
||||
}
|
||||
.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;
|
||||
width: 100% !important;
|
||||
}
|
||||
.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% !important;
|
||||
}
|
||||
.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_list_group_name {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -2621,8 +2697,12 @@
|
|||
.openerp .oe_list_buttons.oe_editing .oe_alternative {
|
||||
visibility: visible;
|
||||
}
|
||||
.openerp .oe_list {
|
||||
position: relative;
|
||||
.openerp .oe_list.oe_cannot_edit .oe_list_header_handle, .openerp .oe_list.oe_cannot_edit .oe_list_field_handle {
|
||||
display: none !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.openerp .oe_list.oe_cannot_delete .oe_list_record_delete {
|
||||
display: none !important;
|
||||
}
|
||||
.openerp .oe_list .oe_form .oe_form_nosheet {
|
||||
margin: 0;
|
||||
|
@ -2635,6 +2715,9 @@
|
|||
margin: 0 !important;
|
||||
padding: 0;
|
||||
}
|
||||
.openerp .oe_list .oe_form .oe_form_field_boolean {
|
||||
padding: 1px 6px 3px;
|
||||
}
|
||||
.openerp .oe_list .oe_list_content .oe_group_header {
|
||||
background-color: #fcfcfc;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcfcfc), to(#dedede));
|
||||
|
@ -2654,6 +2737,9 @@
|
|||
text-align: right !important;
|
||||
max-width: 100px;
|
||||
}
|
||||
.openerp .oe_list_content td.oe_list_field_date, .openerp .oe_list_content th.oe_list_header_date {
|
||||
min-width: 6em;
|
||||
}
|
||||
.openerp .oe_list_content > thead {
|
||||
border-bottom: 2px solid #cacaca;
|
||||
background: #eeeeee;
|
||||
|
@ -2721,6 +2807,10 @@
|
|||
.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_list_field_boolean input {
|
||||
filter: alpha(opacity=50);
|
||||
opacity: 0.5;
|
||||
}
|
||||
.openerp .oe_list_content > tbody > tr:nth-child(odd) {
|
||||
background-color: #f0f0fa;
|
||||
background-color: #f0f0fa;
|
||||
|
@ -2766,12 +2856,8 @@
|
|||
content: "}";
|
||||
color: #e0e0e0;
|
||||
}
|
||||
.openerp .oe_list_cannot_edit .oe_list_header_handle, .openerp .oe_list_cannot_edit .oe_list_field_handle {
|
||||
display: none !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.openerp .oe_list_cannot_delete .oe_list_record_delete {
|
||||
display: none !important;
|
||||
.openerp .oe_list_content .oe_list_field_progressbar progress {
|
||||
width: 100%;
|
||||
}
|
||||
.openerp .tree_header {
|
||||
background-color: #f0f0f0;
|
||||
|
@ -2925,3 +3011,41 @@ div.ui-widget-overlay {
|
|||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.openerp {
|
||||
text-shadow: none;
|
||||
}
|
||||
.openerp .oe_header_row, .openerp ul.oe_header, .openerp div.oe_mail_thread_action, .openerp .oe_mail_recthread_actions, .openerp .oe_button_box, .openerp .oe_form button, .openerp button.oe_invite, .openerp .oe_form header, .openerp .openerp .oe_notebook > li.ui-state-default, .openerp .oe_topbar, .openerp .oe_leftbar, .openerp .oe_loading {
|
||||
display: none !important;
|
||||
}
|
||||
.openerp .oe_list_content button, .openerp .oe_list_content input[type=checkbox] {
|
||||
visibility: hidden;
|
||||
}
|
||||
.openerp .tree_header button, .openerp .oe_mail .oe_mail_thread_msg .oe_mail_unread, .openerp .oe_mail_fetch_more, .openerp .oe_m2o_drop_down_button img, .openerp .oe_form_field_one2many_list_row_add {
|
||||
visibility: hidden;
|
||||
}
|
||||
.openerp a.oe_m2o_cm_button, .openerp a.oe_e {
|
||||
visibility: hidden;
|
||||
}
|
||||
.openerp .oe_form .oe_form_field_date img, .openerp .oe_form .oe_form_field_datetime img {
|
||||
visibility: hidden;
|
||||
}
|
||||
.openerp .oe_notebook > li.ui-tabs-selected {
|
||||
display: block;
|
||||
}
|
||||
.openerp .oe_application .oe_form_sheet, .openerp .oe_application .oe_form_sheetbg {
|
||||
border: 0px !important;
|
||||
box-shadow: 0px 0px 0px;
|
||||
}
|
||||
.openerp .oe_view_manager_current > .oe_view_manager_header {
|
||||
border: 0px !important;
|
||||
box-shadow: 0px 0px 0px;
|
||||
}
|
||||
.openerp .text-core .text-wrap .text-arrow {
|
||||
background: none;
|
||||
}
|
||||
.openerp .openerp div.oe_mail_wall {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ $tag-border-selected: #a6a6fe
|
|||
$hover-background: #f0f0fa
|
||||
$link-color: #7C7BAD
|
||||
$sheet-max-width: 860px
|
||||
$sheet-min-width: 650px
|
||||
$sheet-padding: 16px
|
||||
// }}}
|
||||
// Mixins {{{
|
||||
@font-face
|
||||
|
@ -120,7 +122,7 @@ $sheet-max-width: 860px
|
|||
font-size: 1px
|
||||
letter-spacing: -1px
|
||||
color: transparent
|
||||
font-weight: normal
|
||||
font-weight: normal
|
||||
&:before
|
||||
font: 21px "mnmliconsRegular"
|
||||
content: $icon-name
|
||||
|
@ -130,7 +132,7 @@ $sheet-max-width: 860px
|
|||
font-size: 1px
|
||||
letter-spacing: -1px
|
||||
color: transparent
|
||||
font-weight: normal
|
||||
font-weight: normal
|
||||
&:before
|
||||
font: $size "entypoRegular"
|
||||
content: $icon-name
|
||||
|
@ -138,19 +140,6 @@ $sheet-max-width: 860px
|
|||
|
||||
// }}}
|
||||
|
||||
@media print
|
||||
.oe_topbar, .oe_leftbar, .oe_loading
|
||||
display: none !important
|
||||
|
||||
.openerp.openerp_webclient_container
|
||||
height: 100%
|
||||
position: relative
|
||||
|
||||
// jQueryUI css bug fixing
|
||||
.text-tag .text-button
|
||||
height: auto !important
|
||||
min-height: 16px
|
||||
|
||||
.openerp
|
||||
// Global style {{{
|
||||
padding: 0
|
||||
|
@ -160,6 +149,8 @@ $sheet-max-width: 860px
|
|||
font-size: 13px
|
||||
background: white
|
||||
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5)
|
||||
&.openerp_webclient_container
|
||||
height: 100%
|
||||
// }}}
|
||||
//Placeholder style{{{
|
||||
\:-moz-placeholder
|
||||
|
@ -253,6 +244,16 @@ $sheet-max-width: 860px
|
|||
.oe_bounce_container
|
||||
display: inline-block
|
||||
|
||||
// Bug lp:1051746
|
||||
.text-tag .text-button
|
||||
height: auto !important
|
||||
min-height: 16px
|
||||
|
||||
// bug noted in jquery ui CSS doesn't seem to occur in IE9,
|
||||
// so remove position:relative
|
||||
.ui-tabs
|
||||
position: static
|
||||
|
||||
// Modal box
|
||||
&.ui-dialog
|
||||
display: none
|
||||
|
@ -266,7 +267,7 @@ $sheet-max-width: 860px
|
|||
@include box-shadow(0 1px 12px rgba(0, 0, 0, 0.6))
|
||||
@include background-clip()
|
||||
.ui-dialog-content
|
||||
padding: 0px
|
||||
padding: 0
|
||||
.ui-dialog-titlebar, .ui-dialog-content, .ui-dialog-buttonpane
|
||||
padding: 16px
|
||||
.ui-dialog-titlebar
|
||||
|
@ -563,7 +564,7 @@ $sheet-max-width: 860px
|
|||
position: relative
|
||||
cursor: pointer
|
||||
.oe_dropdown_toggle
|
||||
color: rgba(0,0,0,0.5)
|
||||
color: rgba(0,0,0,0.3)
|
||||
font-weight: normal
|
||||
.oe_dropdown_hover:hover .oe_dropdown_menu, .oe_dropdown_menu.oe_opened
|
||||
display: block
|
||||
|
@ -608,7 +609,7 @@ $sheet-max-width: 860px
|
|||
vertical-align: top
|
||||
margin-top: 8px
|
||||
//margin-left set at 3px to avoid a strange overflow
|
||||
margin-left: 3px
|
||||
margin-left: 3px
|
||||
border-left: 4px solid transparent
|
||||
border-right: 4px solid transparent
|
||||
border-top: 4px solid#404040
|
||||
|
@ -801,7 +802,7 @@ $sheet-max-width: 860px
|
|||
display: none
|
||||
// }}}
|
||||
// Top Menu {{{
|
||||
|
||||
|
||||
.oe_topbar
|
||||
width: 100%
|
||||
height: 32px
|
||||
|
@ -922,6 +923,7 @@ $sheet-max-width: 860px
|
|||
height: 40px
|
||||
width: 157px
|
||||
margin: 14px 0
|
||||
border: 0
|
||||
.oe_footer
|
||||
position: fixed
|
||||
bottom: 0
|
||||
|
@ -974,7 +976,7 @@ $sheet-max-width: 860px
|
|||
.oe_menu_counter
|
||||
float: right
|
||||
text-shadow: 0 1px 1px rgba(0,0,0,0.2)
|
||||
margin: 1px
|
||||
margin: 1px
|
||||
padding: 1px 4px
|
||||
border: none
|
||||
&:hover
|
||||
|
@ -1066,7 +1068,7 @@ $sheet-max-width: 860px
|
|||
// ViewManager common {{{
|
||||
.oe_view_manager
|
||||
.oe_view_manager_body
|
||||
height: inherit
|
||||
height: inherit
|
||||
.oe_view_manager_view_kanban
|
||||
height: inherit
|
||||
|
||||
|
@ -1544,7 +1546,9 @@ $sheet-max-width: 860px
|
|||
padding: 100px 0 0 137px
|
||||
min-height: 327px
|
||||
margin-left: -15px
|
||||
|
||||
.oe_view.oe_cannot_create
|
||||
.oe_view_nocontent_create
|
||||
display: none
|
||||
// }}}
|
||||
// FormView.base and dynamic tags {{{
|
||||
.oe_formview
|
||||
|
@ -1576,7 +1580,7 @@ $sheet-max-width: 860px
|
|||
display: none !important
|
||||
.oe_form .oe_form_field_date
|
||||
width: auto
|
||||
// Sheet and padding
|
||||
// Sheet and padding
|
||||
.oe_form_nosheet
|
||||
margin: 16px
|
||||
> header
|
||||
|
@ -1622,17 +1626,18 @@ $sheet-max-width: 860px
|
|||
margin-left: 6px
|
||||
// }}}
|
||||
// FormView.custom tags and classes {{{
|
||||
.oe_form
|
||||
.oe_form
|
||||
header
|
||||
.oe_tags
|
||||
margin: 5px 0 0 5px
|
||||
width: 400px
|
||||
padding-bottom: 0
|
||||
div.oe_chatter
|
||||
min-width: 650px
|
||||
max-width: $sheet-max-width
|
||||
box-sizing: border-box
|
||||
min-width: $sheet-min-width + 2* $sheet-padding
|
||||
max-width: $sheet-max-width + 2* $sheet-padding
|
||||
margin: 0 auto
|
||||
padding: 16px 0 48px
|
||||
padding: 16px 16px 48px
|
||||
div.oe_form_configuration
|
||||
p, ul, ol
|
||||
color: #aaa
|
||||
|
@ -1785,7 +1790,7 @@ $sheet-max-width: 860px
|
|||
display: none
|
||||
.oe_datepicker_root
|
||||
display: inline-block
|
||||
.oe_form_required
|
||||
.oe_form_required
|
||||
input:not([disabled]):not([readonly]), select:not([disabled]):not([readonly]), textarea:not([disabled]):not([readonly])
|
||||
background-color: #D2D2FF !important
|
||||
.oe_form_invalid
|
||||
|
@ -1821,20 +1826,20 @@ $sheet-max-width: 860px
|
|||
position: relative
|
||||
width: 600px
|
||||
margin-left: 130px
|
||||
margin-top: 32px
|
||||
margin-top: 32px
|
||||
margin-bottom: 32px
|
||||
text-align: justify
|
||||
|
||||
|
||||
.oe_form_editable
|
||||
.oe_form
|
||||
.oe_form_field_integer input
|
||||
width: 6em !important
|
||||
width: 6em
|
||||
.oe_form_field_float input
|
||||
width: 7em !important
|
||||
width: 7em
|
||||
.oe_form_field_date input
|
||||
width: 7.5em !important
|
||||
width: 7.5em
|
||||
.oe_form_field_datetime input
|
||||
width: 11.5em !important
|
||||
width: 11.5em
|
||||
// }}}
|
||||
// FormView.fields_binary {{{
|
||||
/* http://www.quirksmode.org/dom/inputfile.html
|
||||
|
@ -1877,6 +1882,64 @@ $sheet-max-width: 860px
|
|||
@include box-sizing(border)
|
||||
&:hover .oe_form_field_image_controls
|
||||
display: block
|
||||
.oe_fileupload
|
||||
display: inline-block
|
||||
clear: both
|
||||
width: 100%
|
||||
.oe_add
|
||||
float: left
|
||||
position: relative
|
||||
width: 100%
|
||||
left: +2px
|
||||
top: +7px
|
||||
button
|
||||
display: inline
|
||||
height: 24px
|
||||
font-size: 12px
|
||||
line-height: 12px
|
||||
vertical-align: middle
|
||||
button.oe_attach
|
||||
width: 24px
|
||||
overflow: hidden
|
||||
width: 24px
|
||||
overflow: hidden
|
||||
background: transparent
|
||||
color: #7C7BAD
|
||||
box-shadow: none
|
||||
border: none
|
||||
text-shadow: none
|
||||
.oe_e
|
||||
position: relative
|
||||
top: -1px
|
||||
left: -9px
|
||||
input.oe_form_binary_file
|
||||
display: inline-block
|
||||
margin-left: -5px
|
||||
height: 28px
|
||||
width: 52px
|
||||
margin-top: -26px
|
||||
.oe_attach_label
|
||||
color: #7C7BAD
|
||||
margin-left: -3px
|
||||
.oe_attachments
|
||||
margin-bottom: 4px
|
||||
margin-right: 0px
|
||||
font-size: 12px
|
||||
border-radius: 2px
|
||||
border: solid 1px rgba(124,123,173,0.14)
|
||||
.oe_attachment
|
||||
padding: 2px
|
||||
padding-left: 4px
|
||||
padding-right: 4px
|
||||
.oe_e
|
||||
font-size: 23px
|
||||
margin-top: -5px
|
||||
.oe_e:hover
|
||||
text-decoration: none
|
||||
.oe_attachment:nth-child(odd)
|
||||
background: white
|
||||
.oe_attachment:nth-child(even)
|
||||
background: #F4F5FA
|
||||
// }}}
|
||||
// FormView.many2one {{{
|
||||
.oe_form_field_many2one
|
||||
|
@ -1890,6 +1953,8 @@ $sheet-max-width: 860px
|
|||
line-height: 14px
|
||||
float: right
|
||||
padding-left: 2px
|
||||
input
|
||||
padding-right: 13px
|
||||
&.ui-autocomplete
|
||||
li.oe_m2o_dropdown_option a
|
||||
font-style: italic
|
||||
|
@ -1902,7 +1967,7 @@ $sheet-max-width: 860px
|
|||
display: inline-block
|
||||
margin: 0
|
||||
padding: 0 18px 0 0
|
||||
li
|
||||
li
|
||||
display: inline-block
|
||||
list-style-type: none
|
||||
// It is probably a bad idea to modify this margin
|
||||
|
@ -1932,7 +1997,7 @@ $sheet-max-width: 860px
|
|||
vertical-align: top
|
||||
overflow: hidden
|
||||
margin-left: -5px
|
||||
span
|
||||
span
|
||||
position: relative
|
||||
width: 24px
|
||||
height: 24px
|
||||
|
@ -1945,7 +2010,7 @@ $sheet-max-width: 860px
|
|||
@include transform(rotate(45deg))
|
||||
li.oe_active
|
||||
@include vertical-gradient(#729fcf, #3465a4)
|
||||
.arrow span
|
||||
.arrow span
|
||||
@include skew-gradient(#729fcf, #3465a4)
|
||||
.label
|
||||
color: white
|
||||
|
@ -1953,20 +2018,20 @@ $sheet-max-width: 860px
|
|||
ul.oe_form_status_clickable
|
||||
li
|
||||
cursor: pointer
|
||||
&:hover
|
||||
&:hover
|
||||
@include vertical-gradient(darken(#fcfcfc, 8%), darken(#dedede, 8%))
|
||||
.label
|
||||
text-shadow: 0 -1px 1px #fcfcfc, 0 1px 1px #dedede
|
||||
.arrow span
|
||||
.arrow span
|
||||
@include vertical-gradient(darken(#fcfcfc, 8%), darken(#dedede, 8%))
|
||||
.label
|
||||
color: $link-color
|
||||
li.oe_active
|
||||
&:hover
|
||||
&:hover
|
||||
@include vertical-gradient(darken(#729fcf, 10%), darken(#3465a4, 10%))
|
||||
.label
|
||||
text-shadow: 0 -1px 1px #729fcf, 0 1px 1px #3465a4
|
||||
.arrow span
|
||||
.arrow span
|
||||
@include skew-gradient(darken(#729fcf, 10%), darken(#3465a4, 10%))
|
||||
// }}}
|
||||
// FormView.one2many {{{
|
||||
|
@ -1978,6 +2043,9 @@ $sheet-max-width: 860px
|
|||
> .oe_view_manager
|
||||
.oe_list_pager_single_page
|
||||
display: none !important
|
||||
.oe_view_manager_view_list
|
||||
min-height: 132px
|
||||
|
||||
.oe_form_field_one2many_list_row_add
|
||||
font-weight: bold
|
||||
.oe_list_content
|
||||
|
@ -2018,41 +2086,37 @@ $sheet-max-width: 860px
|
|||
background-color: #eee
|
||||
|
||||
$row-height: 27px
|
||||
.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_editable .oe_list_content td.oe_list_field_cell
|
||||
padding: 4px 6px 3px
|
||||
.oe_list.oe_list_editable.oe_editing
|
||||
.oe_edition .oe_list_field_cell:not(.oe_readonly)
|
||||
*
|
||||
visibility: hidden
|
||||
color: transparent
|
||||
text-shadow: none
|
||||
.oe_m2o_drop_down_button
|
||||
top: 5px
|
||||
.oe_m2o_cm_button
|
||||
display: none
|
||||
line-height: 19px
|
||||
.oe_input_icon
|
||||
margin-top: 5px
|
||||
.oe_form_field
|
||||
min-width: 0
|
||||
max-width: none
|
||||
input, textarea
|
||||
height: $row-height
|
||||
input, textarea
|
||||
@include radius(0)
|
||||
border: 1px solid #aaf
|
||||
margin: 0
|
||||
input, textarea, select
|
||||
min-width: 0
|
||||
&.oe_form_field_float,&.oe_form_view_integer
|
||||
input
|
||||
text-align: right
|
||||
width: 100% !important
|
||||
&.oe_form_field_datetime,&.oe_form_field_date
|
||||
> span
|
||||
width: 100% !important
|
||||
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
|
||||
.oe_list_group_name
|
||||
white-space: nowrap
|
||||
// }}}
|
||||
|
@ -2078,7 +2142,14 @@ $sheet-max-width: 860px
|
|||
visibility: visible
|
||||
|
||||
.oe_list
|
||||
position: relative
|
||||
&.oe_cannot_edit
|
||||
.oe_list_header_handle, .oe_list_field_handle
|
||||
display: none !important
|
||||
padding: 0 !important
|
||||
&.oe_cannot_delete
|
||||
.oe_list_record_delete
|
||||
display: none !important
|
||||
|
||||
.oe_form
|
||||
.oe_form_nosheet
|
||||
margin: 0 // FIXME: either class or border should not be by default
|
||||
|
@ -2089,6 +2160,10 @@ $sheet-max-width: 860px
|
|||
position: absolute
|
||||
margin: 0 !important // dammit
|
||||
padding: 0
|
||||
.oe_form_field_boolean
|
||||
// use padding similar to actual cell to correctly position the
|
||||
// checkbox
|
||||
padding: 1px 6px 3px
|
||||
.oe_list_content .oe_group_header
|
||||
@include vertical-gradient(#fcfcfc, #dedede)
|
||||
|
||||
|
@ -2100,6 +2175,8 @@ $sheet-max-width: 860px
|
|||
td.oe_number
|
||||
text-align: right !important
|
||||
max-width: 100px
|
||||
td.oe_list_field_date, th.oe_list_header_date
|
||||
min-width: 6em
|
||||
> thead
|
||||
border-bottom: 2px solid #cacaca
|
||||
background: #eee
|
||||
|
@ -2149,6 +2226,8 @@ $sheet-max-width: 860px
|
|||
width: 17px
|
||||
&:after
|
||||
border-width: 0
|
||||
> td.oe_list_field_boolean input
|
||||
@include opacity()
|
||||
> tr:nth-child(odd)
|
||||
background-color: #f0f0fa
|
||||
@include vertical-gradient(#f0f0fa, #eeeef6)
|
||||
|
@ -2176,15 +2255,8 @@ $sheet-max-width: 860px
|
|||
.oe_list_handle
|
||||
@include text-to-entypo-icon("}",#E0E0E0,18px)
|
||||
margin-right: 7px
|
||||
|
||||
.oe_list_cannot_edit
|
||||
.oe_list_header_handle, .oe_list_field_handle
|
||||
display: none !important
|
||||
padding: 0 !important
|
||||
.oe_list_cannot_delete
|
||||
.oe_list_record_delete
|
||||
display: none !important
|
||||
|
||||
.oe_list_field_progressbar progress
|
||||
width: 100%
|
||||
// }}}
|
||||
// Tree view {{{
|
||||
.tree_header
|
||||
|
@ -2235,7 +2307,6 @@ $sheet-max-width: 860px
|
|||
background-image: url(/web/static/src/img/collapse.gif)
|
||||
.treeview-tr.oe-treeview-first span, .treeview-td.oe-treeview-first span
|
||||
margin-left: 16px
|
||||
|
||||
// }}}
|
||||
// Debugging stuff {{{
|
||||
.oe_layout_debugging
|
||||
|
@ -2278,14 +2349,15 @@ $sheet-max-width: 860px
|
|||
background-attachment: fixed
|
||||
>*
|
||||
opacity: 0.70
|
||||
|
||||
// }}}
|
||||
|
||||
// jQueryUI top level {{{
|
||||
// The jQuery-ui overlay and Autocomplete are outside the .openerp div, please don't add indentation !!!
|
||||
div.ui-widget-overlay
|
||||
background: black
|
||||
@include opacity(0.3)
|
||||
|
||||
// TODO: I think only the overlay is problematic, the other top level widgets should use $.fn.openerpClass()
|
||||
// eg: $el.autocomplete().openerpClass();
|
||||
.ui-widget
|
||||
font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif
|
||||
color: #4c4c4c
|
||||
|
@ -2300,7 +2372,7 @@ div.ui-widget-overlay
|
|||
width: 100%
|
||||
padding: 0
|
||||
a
|
||||
padding: 1px 16px
|
||||
padding: 1px 16px
|
||||
a.ui-corner-all
|
||||
@include radius(0)
|
||||
a.ui-state-active
|
||||
|
@ -2312,6 +2384,40 @@ div.ui-widget-overlay
|
|||
|
||||
.ui-corner-all
|
||||
@include radius(3px)
|
||||
// }}}
|
||||
|
||||
// @media print {{{
|
||||
@media print
|
||||
.openerp
|
||||
.oe_header_row, ul.oe_header, div.oe_mail_thread_action, .oe_mail_recthread_actions, .oe_button_box, .oe_form button, button.oe_invite, .oe_form header, .openerp .oe_notebook > li.ui-state-default, .oe_topbar, .oe_leftbar, .oe_loading
|
||||
// We use !important here because jQuery adds @style = display: block on elements when using $.fn.show()
|
||||
display: none !important
|
||||
.oe_list_content
|
||||
button, input[type=checkbox]
|
||||
visibility: hidden
|
||||
.tree_header button, .oe_mail .oe_mail_thread_msg .oe_mail_unread, .oe_mail_fetch_more, .oe_m2o_drop_down_button img, .oe_form_field_one2many_list_row_add
|
||||
visibility: hidden
|
||||
a
|
||||
&.oe_m2o_cm_button, &.oe_e
|
||||
visibility: hidden
|
||||
.oe_form
|
||||
.oe_form_field_date img, .oe_form_field_datetime img
|
||||
visibility: hidden
|
||||
.oe_notebook > li.ui-tabs-selected
|
||||
display: block
|
||||
.oe_application
|
||||
.oe_form_sheet, .oe_form_sheetbg
|
||||
border: 0px !important
|
||||
box-shadow: 0px 0px 0px
|
||||
.oe_view_manager_current > .oe_view_manager_header
|
||||
border: 0px !important
|
||||
box-shadow: 0px 0px 0px
|
||||
text-shadow: none
|
||||
.text-core .text-wrap .text-arrow
|
||||
background: none
|
||||
.openerp div.oe_mail_wall
|
||||
overflow: hidden !important
|
||||
// }}}
|
||||
|
||||
// au BufWritePost,FileWritePost *.sass :!sass --style expanded --line-numbers <afile> > "%:p:r.css"
|
||||
// vim:tabstop=4:shiftwidth=4:softtabstop=4:fdm=marker:
|
||||
|
|
|
@ -48,7 +48,7 @@ instance.web.Notification = instance.web.Widget.extend({
|
|||
*/
|
||||
instance.web.dialog = function(element) {
|
||||
var result = element.dialog.apply(element, _.rest(_.toArray(arguments)));
|
||||
result.dialog("widget").addClass("openerp");
|
||||
result.dialog("widget").openerpClass();
|
||||
return result;
|
||||
};
|
||||
|
||||
|
@ -81,9 +81,6 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
}
|
||||
}
|
||||
if (options) {
|
||||
if (options.buttons) {
|
||||
this.params_buttons = true;
|
||||
}
|
||||
_.extend(this.dialog_options, options);
|
||||
}
|
||||
this.on("closing", this, this._closing);
|
||||
|
@ -129,6 +126,8 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
if (! this.dialog_inited)
|
||||
this.init_dialog();
|
||||
var o = this.get_options(options);
|
||||
this.add_buttons(o.buttons);
|
||||
delete(o.buttons);
|
||||
this.$buttons.appendTo($("body"));
|
||||
instance.web.dialog(this.$el, o).dialog('open');
|
||||
this.$el.dialog("widget").find(".ui-dialog-buttonpane").remove();
|
||||
|
@ -138,22 +137,30 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
}
|
||||
return this;
|
||||
},
|
||||
add_buttons: function(buttons) {
|
||||
var self = this;
|
||||
_.each(buttons, function(fn, but) {
|
||||
var $but = $(QWeb.render('WidgetButton', { widget : { string: but, node: { attrs: {} }}}));
|
||||
self.$buttons.append($but);
|
||||
$but.on('click', function(ev) {
|
||||
fn.call(self.$el, ev);
|
||||
});
|
||||
});
|
||||
},
|
||||
init_dialog: function(options) {
|
||||
this.renderElement();
|
||||
var o = this.get_options(options);
|
||||
instance.web.dialog(this.$el, o);
|
||||
if (! this.params_buttons) {
|
||||
this.$buttons = $('<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" />');
|
||||
this.$el.dialog("widget").append(this.$buttons);
|
||||
} else {
|
||||
this.$buttons = this.$el.dialog("widget").find(".ui-dialog-buttonpane");
|
||||
}
|
||||
this.$buttons = $('<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" />');
|
||||
this.$el.dialog("widget").append(this.$buttons);
|
||||
this.dialog_inited = true;
|
||||
var res = this.start();
|
||||
return res;
|
||||
},
|
||||
close: function() {
|
||||
this.$el.dialog('close');
|
||||
if (this.dialog_inited && this.$el.is(":data(dialog)")) {
|
||||
this.$el.dialog('close');
|
||||
}
|
||||
},
|
||||
_closing: function() {
|
||||
if (this.__tmp_dialog_destroying)
|
||||
|
@ -175,15 +182,22 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
this.close();
|
||||
this.__tmp_dialog_destroying = undefined;
|
||||
}
|
||||
if (! this.isDestroyed()) {
|
||||
if (this.dialog_inited && !this.isDestroyed()) {
|
||||
this.$el.dialog('destroy');
|
||||
}
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
||||
instance.web.CrashManager = instance.web.CallbackEnabled.extend({
|
||||
instance.web.CrashManager = instance.web.Class.extend({
|
||||
init: function() {
|
||||
this.active = true;
|
||||
},
|
||||
|
||||
rpc_error: function(error) {
|
||||
if (!this.active) {
|
||||
return;
|
||||
}
|
||||
if (error.data.fault_code) {
|
||||
var split = ("" + error.data.fault_code).split('\n')[0].split(' -- ');
|
||||
if (split.length > 1) {
|
||||
|
@ -198,6 +212,9 @@ instance.web.CrashManager = instance.web.CallbackEnabled.extend({
|
|||
}
|
||||
},
|
||||
show_warning: function(error) {
|
||||
if (!this.active) {
|
||||
return;
|
||||
}
|
||||
instance.web.dialog($('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>'), {
|
||||
title: "OpenERP " + _.str.capitalize(error.type),
|
||||
buttons: [
|
||||
|
@ -206,7 +223,9 @@ instance.web.CrashManager = instance.web.CallbackEnabled.extend({
|
|||
});
|
||||
},
|
||||
show_error: function(error) {
|
||||
var self = this;
|
||||
if (!this.active) {
|
||||
return;
|
||||
}
|
||||
var buttons = {};
|
||||
buttons[_t("Ok")] = function() {
|
||||
$(this).dialog("close");
|
||||
|
@ -294,7 +313,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
|
|||
start: function() {
|
||||
var self = this;
|
||||
$('.oe_secondary_menus_container,.oe_user_menu_placeholder').empty();
|
||||
var fetch_db = this.rpc("/web/database/get_list", {}).pipe(
|
||||
var fetch_db = this.rpc("/web/database/get_list", {}).then(
|
||||
function(result) {
|
||||
self.db_list = result;
|
||||
},
|
||||
|
@ -302,10 +321,10 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
|
|||
ev.preventDefault();
|
||||
self.db_list = null;
|
||||
});
|
||||
var fetch_langs = this.rpc("/web/session/get_lang_list", {}).then(function(result) {
|
||||
var fetch_langs = this.rpc("/web/session/get_lang_list", {}).done(function(result) {
|
||||
self.lang_list = result;
|
||||
});
|
||||
return $.when(fetch_db, fetch_langs).then(self.do_render);
|
||||
return $.when(fetch_db, fetch_langs).done(self.do_render);
|
||||
},
|
||||
do_render: function() {
|
||||
var self = this;
|
||||
|
@ -395,7 +414,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
|
|||
do_create: function(form) {
|
||||
var self = this;
|
||||
var fields = $(form).serializeArray();
|
||||
self.rpc("/web/database/create", {'fields': fields}).then(function(result) {
|
||||
self.rpc("/web/database/create", {'fields': fields}).done(function(result) {
|
||||
var form_obj = self.to_object(fields);
|
||||
var client_action = {
|
||||
type: 'ir.actions.client',
|
||||
|
@ -433,7 +452,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
|
|||
if (!db || !confirm("Do you really want to delete the database: " + db + " ?")) {
|
||||
return;
|
||||
}
|
||||
self.rpc("/web/database/drop", {'fields': fields}).then(function(result) {
|
||||
self.rpc("/web/database/drop", {'fields': fields}).done(function(result) {
|
||||
if (result.error) {
|
||||
self.display_error(result);
|
||||
return;
|
||||
|
@ -496,7 +515,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
|
|||
var self = this;
|
||||
self.rpc("/web/database/change_password", {
|
||||
'fields': $(form).serializeArray()
|
||||
}).then(function(result) {
|
||||
}).done(function(result) {
|
||||
if (result.error) {
|
||||
self.display_error(result);
|
||||
return;
|
||||
|
@ -517,13 +536,16 @@ instance.web.Login = instance.web.Widget.extend({
|
|||
template: "Login",
|
||||
remember_credentials: true,
|
||||
|
||||
init: function(parent, params) {
|
||||
init: function(parent, action) {
|
||||
this._super(parent);
|
||||
this.has_local_storage = typeof(localStorage) != 'undefined';
|
||||
this.db_list = null;
|
||||
this.selected_db = null;
|
||||
this.selected_login = null;
|
||||
this.params = params || {};
|
||||
this.params = action.params || {};
|
||||
if (_.isEmpty(this.params)) {
|
||||
this.params = $.bbq.getState(true);
|
||||
}
|
||||
|
||||
if (this.params.login_successful) {
|
||||
this.on('login_successful', this, this.params.login_successful);
|
||||
|
@ -554,7 +576,7 @@ instance.web.Login = instance.web.Widget.extend({
|
|||
return d;
|
||||
},
|
||||
on_db_loaded: function (result) {
|
||||
this.db_list = result.db_list;
|
||||
this.db_list = result;
|
||||
this.$("[name=db]").replaceWith(QWeb.render('Login.dblist', { db_list: this.db_list, selected_db: this.selected_db}));
|
||||
if(this.db_list.length === 0) {
|
||||
this.do_action("database_manager");
|
||||
|
@ -594,7 +616,7 @@ instance.web.Login = instance.web.Widget.extend({
|
|||
var self = this;
|
||||
self.hide_error();
|
||||
self.$(".oe_login_pane").fadeOut("slow");
|
||||
return this.session.session_authenticate(db, login, password).pipe(function() {
|
||||
return this.session.session_authenticate(db, login, password).then(function() {
|
||||
if (self.has_local_storage) {
|
||||
if(self.remember_credentials) {
|
||||
localStorage.setItem('last_db_login_success', db);
|
||||
|
@ -626,11 +648,38 @@ instance.web.Login = instance.web.Widget.extend({
|
|||
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.
|
||||
* Redirect to url by replacing window.location
|
||||
* If wait is true, sleep 1s and wait for the server i.e. after a restart.
|
||||
*/
|
||||
instance.web.Reload = function(parent, params) {
|
||||
var menu_id = (params && params.menu_id) || false;
|
||||
instance.web.redirect = function(url, wait) {
|
||||
// Dont display a dialog if some xmlhttprequest are in progress
|
||||
if (instance.client && instance.client.crashmanager) {
|
||||
instance.client.crashmanager.active = false;
|
||||
}
|
||||
|
||||
var wait_server = function() {
|
||||
instance.session.rpc("/web/webclient/version_info", {}).done(function() {
|
||||
window.location = url;
|
||||
}).fail(function() {
|
||||
setTimeout(wait_server, 250);
|
||||
});
|
||||
};
|
||||
|
||||
if (wait) {
|
||||
setTimeout(wait_server, 1000);
|
||||
} else {
|
||||
window.location = url;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Client action to reload the whole interface.
|
||||
* If params.menu_id, it opens the given menu entry.
|
||||
* If params.wait, reload will wait the openerp server to be reachable before reloading
|
||||
*/
|
||||
instance.web.Reload = function(parent, action) {
|
||||
var params = action.params || {};
|
||||
var menu_id = params.menu_id || false;
|
||||
var l = window.location;
|
||||
|
||||
var sobj = $.deparam(l.search.substr(1));
|
||||
|
@ -642,8 +691,8 @@ instance.web.Reload = function(parent, params) {
|
|||
hash = "#menu_id=" + menu_id;
|
||||
}
|
||||
var url = l.protocol + "//" + l.host + l.pathname + search + hash;
|
||||
window.onerror = function() {};
|
||||
window.location = url;
|
||||
|
||||
instance.web.redirect(url, params.wait);
|
||||
};
|
||||
instance.web.client_actions.add("reload", "instance.web.Reload");
|
||||
|
||||
|
@ -651,9 +700,9 @@ 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 = function(parent, params) {
|
||||
instance.web.HistoryBack = function(parent) {
|
||||
if (!parent.history_back()) {
|
||||
window.location = '/' + (window.location.search || '');
|
||||
instance.web.Home(parent);
|
||||
}
|
||||
};
|
||||
instance.web.client_actions.add("history_back", "instance.web.HistoryBack");
|
||||
|
@ -661,11 +710,10 @@ 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.Home = function(parent, action) {
|
||||
var url = '/' + (window.location.search || '');
|
||||
instance.web.redirect(url, action.params && action.params.wait);
|
||||
};
|
||||
instance.web.client_actions.add("home", "instance.web.Home");
|
||||
|
||||
instance.web.ChangePassword = instance.web.Widget.extend({
|
||||
|
@ -676,7 +724,7 @@ instance.web.ChangePassword = instance.web.Widget.extend({
|
|||
submitHandler: function (form) {
|
||||
self.rpc("/web/session/change_password",{
|
||||
'fields': $(form).serializeArray()
|
||||
}).then(function(result) {
|
||||
}).done(function(result) {
|
||||
if (result.error) {
|
||||
self.display_error(result);
|
||||
return;
|
||||
|
@ -715,7 +763,7 @@ instance.web.Menu = instance.web.Widget.extend({
|
|||
},
|
||||
do_reload: function() {
|
||||
var self = this;
|
||||
return this.rpc("/web/menu/load", {}).then(function(r) {
|
||||
return this.rpc("/web/menu/load", {}).done(function(r) {
|
||||
self.menu_loaded(r);
|
||||
});
|
||||
},
|
||||
|
@ -885,18 +933,18 @@ instance.web.UserMenu = instance.web.Widget.extend({
|
|||
if (!self.session.uid)
|
||||
return;
|
||||
var func = new instance.web.Model("res.users").get_func("read");
|
||||
return func(self.session.uid, ["name", "company_id"]).pipe(function(res) {
|
||||
return func(self.session.uid, ["name", "company_id"]).then(function(res) {
|
||||
var topbar_name = res.name;
|
||||
if(instance.session.debug)
|
||||
topbar_name = _.str.sprintf("%s (%s)", topbar_name, instance.session.db);
|
||||
if(res.company_id[0] > 1)
|
||||
topbar_name = _.str.sprintf("%s (%s)", topbar_name, res.company_id[1]);
|
||||
self.$el.find('.oe_topbar_name').text(topbar_name);
|
||||
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);
|
||||
var avatar_src = self.session.url('/web/binary/image', {model:'res.users', field: 'image_small', id: self.session.uid});
|
||||
$avatar.attr('src', avatar_src);
|
||||
});
|
||||
};
|
||||
this.update_promise = this.update_promise.pipe(fct, fct);
|
||||
this.update_promise = this.update_promise.then(fct, fct);
|
||||
},
|
||||
on_menu_logout: function() {
|
||||
this.trigger('user_logout');
|
||||
|
@ -904,7 +952,7 @@ instance.web.UserMenu = instance.web.Widget.extend({
|
|||
on_menu_settings: function() {
|
||||
var self = this;
|
||||
if (!this.getParent().has_uncommitted_changes()) {
|
||||
self.rpc("/web/action/load", { action_id: "base.action_res_users_my" }, function(result) {
|
||||
self.rpc("/web/action/load", { action_id: "base.action_res_users_my" }).done(function(result) {
|
||||
result.res_id = instance.session.uid;
|
||||
self.getParent().action_manager.do_action(result);
|
||||
});
|
||||
|
@ -912,7 +960,7 @@ instance.web.UserMenu = instance.web.Widget.extend({
|
|||
},
|
||||
on_menu_about: function() {
|
||||
var self = this;
|
||||
self.rpc("/web/webclient/version_info", {}).then(function(res) {
|
||||
self.rpc("/web/webclient/version_info", {}).done(function(res) {
|
||||
var $help = $(QWeb.render("UserMenu.about", {version_info: res}));
|
||||
$help.find('a.oe_activate_debug_mode').click(function (e) {
|
||||
e.preventDefault();
|
||||
|
@ -932,9 +980,10 @@ instance.web.Client = instance.web.Widget.extend({
|
|||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
return instance.session.session_bind(this.origin).pipe(function() {
|
||||
return instance.session.session_bind(this.origin).then(function() {
|
||||
var $e = $(QWeb.render(self._template, {}));
|
||||
self.replaceElement($e);
|
||||
$e.openerpClass();
|
||||
self.bind_events();
|
||||
return self.show_common();
|
||||
});
|
||||
|
@ -999,7 +1048,7 @@ instance.web.WebClient = instance.web.Client.extend({
|
|||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
return $.when(this._super()).pipe(function() {
|
||||
return $.when(this._super()).then(function() {
|
||||
self.$el.on('click', '.oe_logo', function() {
|
||||
self.action_manager.do_action('home');
|
||||
});
|
||||
|
@ -1068,8 +1117,8 @@ instance.web.WebClient = instance.web.Client.extend({
|
|||
},
|
||||
do_reload: function() {
|
||||
var self = this;
|
||||
return this.session.session_reload().pipe(function () {
|
||||
instance.session.load_modules(true).pipe(
|
||||
return this.session.session_reload().then(function () {
|
||||
instance.session.load_modules(true).then(
|
||||
self.menu.proxy('do_reload')); });
|
||||
|
||||
},
|
||||
|
@ -1084,7 +1133,7 @@ instance.web.WebClient = instance.web.Client.extend({
|
|||
on_logout: function() {
|
||||
var self = this;
|
||||
if (!this.has_uncommitted_changes()) {
|
||||
this.session.session_logout().then(function () {
|
||||
this.session.session_logout().done(function () {
|
||||
$(window).unbind('hashchange', self.on_hashchange);
|
||||
self.do_push_state({});
|
||||
window.location.reload();
|
||||
|
@ -1097,7 +1146,7 @@ instance.web.WebClient = instance.web.Client.extend({
|
|||
|
||||
var state = $.bbq.getState(true);
|
||||
if (_.isEmpty(state) || state.action == "login") {
|
||||
self.menu.has_been_loaded.then(function() {
|
||||
self.menu.has_been_loaded.done(function() {
|
||||
var first_menu_id = self.menu.$el.find("a:first").data("menu");
|
||||
if(first_menu_id) {
|
||||
self.menu.menu_click(first_menu_id);
|
||||
|
@ -1111,10 +1160,10 @@ instance.web.WebClient = instance.web.Client.extend({
|
|||
var self = this;
|
||||
var state = event.getState(true);
|
||||
if (!_.isEqual(this._current_state, state)) {
|
||||
if(state.action_id === undefined && state.menu_id) {
|
||||
self.menu.has_been_loaded.then(function() {
|
||||
self.menu.do_reload().then(function() {
|
||||
self.menu.menu_click(state.menu_id)
|
||||
if(!state.action && state.menu_id) {
|
||||
self.menu.has_been_loaded.done(function() {
|
||||
self.menu.do_reload().done(function() {
|
||||
self.menu.menu_click(state.menu_id);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
|
@ -1130,17 +1179,19 @@ instance.web.WebClient = instance.web.Client.extend({
|
|||
var url = '#' + $.param(state);
|
||||
this._current_state = _.clone(state);
|
||||
$.bbq.pushState(url);
|
||||
this.trigger('state_pushed', state);
|
||||
},
|
||||
on_menu_action: function(options) {
|
||||
var self = this;
|
||||
return this.rpc("/web/action/load", { action_id: options.action_id })
|
||||
.pipe(function (result) {
|
||||
.then(function (result) {
|
||||
var action = result;
|
||||
if (options.needaction) {
|
||||
action.context.search_default_message_unread = true;
|
||||
}
|
||||
return $.when(self.action_manager.do_action(action, {
|
||||
clear_breadcrumbs: true,
|
||||
action_menu_id: self.menu.current_menu,
|
||||
})).fail(function() {
|
||||
self.menu.open_menu(options.previous_menu_id);
|
||||
});
|
||||
|
@ -1179,9 +1230,9 @@ instance.web.EmbeddedClient = instance.web.Client.extend({
|
|||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
return $.when(this._super()).pipe(function() {
|
||||
return instance.session.session_authenticate(self.dbname, self.login, self.key, true).pipe(function() {
|
||||
return self.rpc("/web/action/load", { action_id: self.action_id }).then(function(result) {
|
||||
return $.when(this._super()).then(function() {
|
||||
return instance.session.session_authenticate(self.dbname, self.login, self.key, true).then(function() {
|
||||
return self.rpc("/web/action/load", { action_id: self.action_id }).done(function(result) {
|
||||
var action = result;
|
||||
action.flags = _.extend({
|
||||
//views_switcher : false,
|
||||
|
|
|
@ -243,15 +243,17 @@ instance.web.ParentedMixin = {
|
|||
|
||||
/**
|
||||
* Backbone's events. Do not ever use it directly, use EventDispatcherMixin instead.
|
||||
*
|
||||
* This class just handle the dispatching of events, it is not meant to be extended,
|
||||
* nor used directly. All integration with parenting and automatic unregistration of
|
||||
* events is done in EventDispatcherMixin.
|
||||
*
|
||||
* Copyright notice for the following Class:
|
||||
*
|
||||
* (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
* Backbone may be freely distributed under the MIT license.
|
||||
* For all details and documentation:
|
||||
* http://backbonejs.org
|
||||
*
|
||||
* This class just handle the dispatching of events, it is not meant to be extended,
|
||||
* nor used directly. All integration with parenting and automatic unregistration of
|
||||
* events is done in EventDispatcherMixin.
|
||||
*
|
||||
*/
|
||||
var Events = instance.web.Class.extend({
|
||||
|
@ -334,7 +336,6 @@ var Events = instance.web.Class.extend({
|
|||
return this;
|
||||
}
|
||||
});
|
||||
// end of Jeremy Ashkenas' code
|
||||
|
||||
instance.web.EventDispatcherMixin = _.extend({}, instance.web.ParentedMixin, {
|
||||
__eventDispatcherMixin: true,
|
||||
|
@ -426,66 +427,94 @@ instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, {
|
|||
}
|
||||
});
|
||||
|
||||
instance.web.CallbackEnabledMixin = _.extend({}, instance.web.PropertiesMixin, {
|
||||
init: function() {
|
||||
instance.web.PropertiesMixin.init.call(this);
|
||||
var self = this;
|
||||
// Transform on_/do_* methods into callbacks
|
||||
var callback_maker = function(fn) {
|
||||
return function() {
|
||||
return fn.apply(self, arguments);
|
||||
}
|
||||
};
|
||||
for (var name in this) {
|
||||
if(typeof(this[name]) == "function") {
|
||||
if((/^on_|^do_/).test(name)) {
|
||||
this[name] = callback_maker(this[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Proxies a method of the object, in order to keep the right ``this`` on
|
||||
* method invocations.
|
||||
*
|
||||
* This method is similar to ``Function.prototype.bind`` or ``_.bind``, and
|
||||
* even more so to ``jQuery.proxy`` with a fundamental difference: its
|
||||
* resolution of the method being called is lazy, meaning it will use the
|
||||
* method as it is when the proxy is called, not when the proxy is created.
|
||||
*
|
||||
* Other methods will fix the bound method to what it is when creating the
|
||||
* binding/proxy, which is fine in most javascript code but problematic in
|
||||
* OpenERP Web where developers may want to replace existing callbacks with
|
||||
* theirs.
|
||||
*
|
||||
* The semantics of this precisely replace closing over the method call.
|
||||
*
|
||||
* @param {String|Function} method function or name of the method to invoke
|
||||
* @returns {Function} proxied method
|
||||
*/
|
||||
proxy: function (method) {
|
||||
var self = this;
|
||||
return function () {
|
||||
var fn = (typeof method === 'string') ? self[method] : method;
|
||||
return fn.apply(self, arguments);
|
||||
}
|
||||
}
|
||||
});
|
||||
// Classes
|
||||
|
||||
instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, {
|
||||
/**
|
||||
* Base class for all visual components. Provides a lot of functionalities helpful
|
||||
* for the management of a part of the DOM.
|
||||
*
|
||||
* Widget handles:
|
||||
* - Rendering with QWeb.
|
||||
* - Life-cycle management and parenting (when a parent is destroyed, all its children are
|
||||
* destroyed too).
|
||||
* - Insertion in DOM.
|
||||
*
|
||||
* Guide to create implementations of the Widget class:
|
||||
* ==============================================
|
||||
*
|
||||
* Here is a sample child class:
|
||||
*
|
||||
* MyWidget = instance.base.Widget.extend({
|
||||
* // the name of the QWeb template to use for rendering
|
||||
* template: "MyQWebTemplate",
|
||||
*
|
||||
* init: function(parent) {
|
||||
* this._super(parent);
|
||||
* // stuff that you want to init before the rendering
|
||||
* },
|
||||
* start: function() {
|
||||
* // stuff you want to make after the rendering, `this.$el` holds a correct value
|
||||
* this.$el.find(".my_button").click(/* an example of event binding * /);
|
||||
*
|
||||
* // if you have some asynchronous operations, it's a good idea to return
|
||||
* // a promise in start()
|
||||
* var promise = this.rpc(...);
|
||||
* return promise;
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Now this class can simply be used with the following syntax:
|
||||
*
|
||||
* var my_widget = new MyWidget(this);
|
||||
* my_widget.appendTo($(".some-div"));
|
||||
*
|
||||
* With these two lines, the MyWidget instance was inited, rendered, it was inserted into the
|
||||
* DOM inside the ".some-div" div and its events were binded.
|
||||
*
|
||||
* And of course, when you don't need that widget anymore, just do:
|
||||
*
|
||||
* my_widget.destroy();
|
||||
*
|
||||
* 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.PropertiesMixin, {
|
||||
// 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.
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
template: null,
|
||||
/**
|
||||
* Constructs the widget and sets its parent if a parent is given.
|
||||
*
|
||||
* @constructs instance.web.Widget
|
||||
* @extends instance.web.CallbackEnabled
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
init: function(parent) {
|
||||
instance.web.CallbackEnabledMixin.init.call(this);
|
||||
instance.web.PropertiesMixin.init.call(this);
|
||||
this.setParent(parent);
|
||||
// Bind on_/do_* methods to this
|
||||
// We might remove this automatic binding in the future
|
||||
for (var name in this) {
|
||||
if(typeof(this[name]) == "function") {
|
||||
if((/^on_|^do_/).test(name)) {
|
||||
this[name] = this[name].bind(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME: this should not be
|
||||
this.setElement(this._make_descriptive());
|
||||
this.session = instance.session;
|
||||
},
|
||||
/**
|
||||
* Destroys the current widget, also destroys all its children before destroying itself.
|
||||
|
@ -574,94 +603,32 @@ instance.web.WidgetMixin = _.extend({},instance.web.CallbackEnabledMixin, {
|
|||
*/
|
||||
start: function() {
|
||||
return $.when();
|
||||
}
|
||||
});
|
||||
|
||||
// Classes
|
||||
|
||||
instance.web.CallbackEnabled = instance.web.Class.extend(instance.web.CallbackEnabledMixin, {
|
||||
init: function() {
|
||||
instance.web.CallbackEnabledMixin.init.call(this);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Base class for all visual components. Provides a lot of functionalities helpful
|
||||
* for the management of a part of the DOM.
|
||||
*
|
||||
* Widget handles:
|
||||
* - Rendering with QWeb.
|
||||
* - Life-cycle management and parenting (when a parent is destroyed, all its children are
|
||||
* destroyed too).
|
||||
* - Insertion in DOM.
|
||||
*
|
||||
* Guide to create implementations of the Widget class:
|
||||
* ==============================================
|
||||
*
|
||||
* Here is a sample child class:
|
||||
*
|
||||
* MyWidget = instance.base.Widget.extend({
|
||||
* // the name of the QWeb template to use for rendering
|
||||
* template: "MyQWebTemplate",
|
||||
*
|
||||
* init: function(parent) {
|
||||
* this._super(parent);
|
||||
* // stuff that you want to init before the rendering
|
||||
* },
|
||||
* start: function() {
|
||||
* // stuff you want to make after the rendering, `this.$el` holds a correct value
|
||||
* this.$el.find(".my_button").click(/* an example of event binding * /);
|
||||
*
|
||||
* // if you have some asynchronous operations, it's a good idea to return
|
||||
* // a promise in start()
|
||||
* var promise = this.rpc(...);
|
||||
* return promise;
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Now this class can simply be used with the following syntax:
|
||||
*
|
||||
* var my_widget = new MyWidget(this);
|
||||
* my_widget.appendTo($(".some-div"));
|
||||
*
|
||||
* With these two lines, the MyWidget instance was inited, rendered, it was inserted into the
|
||||
* DOM inside the ".some-div" div and its events were binded.
|
||||
*
|
||||
* And of course, when you don't need that widget anymore, just do:
|
||||
*
|
||||
* my_widget.destroy();
|
||||
*
|
||||
* 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.
|
||||
* Proxies a method of the object, in order to keep the right ``this`` on
|
||||
* method invocations.
|
||||
*
|
||||
* @type string
|
||||
* This method is similar to ``Function.prototype.bind`` or ``_.bind``, and
|
||||
* even more so to ``jQuery.proxy`` with a fundamental difference: its
|
||||
* resolution of the method being called is lazy, meaning it will use the
|
||||
* method as it is when the proxy is called, not when the proxy is created.
|
||||
*
|
||||
* Other methods will fix the bound method to what it is when creating the
|
||||
* binding/proxy, which is fine in most javascript code but problematic in
|
||||
* OpenERP Web where developers may want to replace existing callbacks with
|
||||
* theirs.
|
||||
*
|
||||
* The semantics of this precisely replace closing over the method call.
|
||||
*
|
||||
* @param {String|Function} method function or name of the method to invoke
|
||||
* @returns {Function} proxied method
|
||||
*/
|
||||
template: null,
|
||||
/**
|
||||
* Constructs the widget and sets its parent if a parent is given.
|
||||
*
|
||||
* @constructs instance.web.Widget
|
||||
* @extends instance.web.CallbackEnabled
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
init: function(parent) {
|
||||
instance.web.WidgetMixin.init.call(this,parent);
|
||||
// FIXME: this should not be
|
||||
this.setElement(this._make_descriptive());
|
||||
this.session = instance.session;
|
||||
proxy: function (method) {
|
||||
var self = this;
|
||||
return function () {
|
||||
var fn = (typeof method === 'string') ? self[method] : method;
|
||||
return fn.apply(self, arguments);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Renders the element. The default implementation renders the widget using QWeb,
|
||||
|
@ -678,7 +645,6 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, {
|
|||
}
|
||||
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.
|
||||
|
@ -808,13 +774,13 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, {
|
|||
}
|
||||
return false;
|
||||
},
|
||||
rpc: function(url, data, success, error) {
|
||||
var def = $.Deferred().then(success, error);
|
||||
rpc: function(url, data, options) {
|
||||
var def = $.Deferred();
|
||||
var self = this;
|
||||
instance.session.rpc(url, data).then(function() {
|
||||
instance.session.rpc(url, data, options).done(function() {
|
||||
if (!self.isDestroyed())
|
||||
def.resolve.apply(def, arguments);
|
||||
}, function() {
|
||||
}).fail(function() {
|
||||
if (!self.isDestroyed())
|
||||
def.reject.apply(def, arguments);
|
||||
});
|
||||
|
@ -941,7 +907,7 @@ instance.web.Registry = instance.web.Class.extend({
|
|||
}
|
||||
});
|
||||
|
||||
instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
||||
instance.web.JsonRPC = instance.web.Class.extend(instance.web.PropertiesMixin, {
|
||||
triggers: {
|
||||
'request': 'Request sent',
|
||||
'response': 'Response received',
|
||||
|
@ -950,13 +916,12 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
|||
},
|
||||
/**
|
||||
* @constructs instance.web.JsonRPC
|
||||
* @extends instance.web.CallbackEnabled
|
||||
*
|
||||
* @param {String} [server] JSON-RPC endpoint hostname
|
||||
* @param {String} [port] JSON-RPC endpoint port
|
||||
*/
|
||||
init: function() {
|
||||
this._super();
|
||||
instance.web.PropertiesMixin.init.call(this);
|
||||
this.server = null;
|
||||
this.debug = ($.deparam($.param.querystring()).debug != undefined);
|
||||
},
|
||||
|
@ -1266,12 +1231,14 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
|||
*
|
||||
* @param {String} url RPC endpoint
|
||||
* @param {Object} params call parameters
|
||||
* @param {Object} options additional options for rpc call
|
||||
* @param {Function} success_callback function to execute on RPC call success
|
||||
* @param {Function} error_callback function to execute on RPC call failure
|
||||
* @returns {jQuery.Deferred} jquery-provided ajax deferred
|
||||
*/
|
||||
rpc: function(url, params) {
|
||||
rpc: function(url, params, options) {
|
||||
var self = this;
|
||||
options = options || {};
|
||||
// url can be an $.ajax option object
|
||||
if (_.isString(url)) {
|
||||
url = { url: url };
|
||||
|
@ -1286,10 +1253,12 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
|||
id: _.uniqueId('r')
|
||||
};
|
||||
var deferred = $.Deferred();
|
||||
this.trigger('request', url, payload);
|
||||
var request = this.rpc_function(url, payload).then(
|
||||
if (! options.shadow)
|
||||
this.trigger('request', url, payload);
|
||||
var request = this.rpc_function(url, payload).done(
|
||||
function (response, textStatus, jqXHR) {
|
||||
self.trigger('response', response);
|
||||
if (! options.shadow)
|
||||
self.trigger('response', response);
|
||||
if (!response.error) {
|
||||
if (url.url === '/web/session/eval_domain_and_context') {
|
||||
self.test_eval(params, response.result);
|
||||
|
@ -1300,9 +1269,11 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
|||
} else {
|
||||
deferred.reject(response.error, $.Event());
|
||||
}
|
||||
},
|
||||
}
|
||||
).fail(
|
||||
function(jqXHR, textStatus, errorThrown) {
|
||||
self.trigger('response_failed', jqXHR);
|
||||
if (! options.shadow)
|
||||
self.trigger('response_failed', jqXHR);
|
||||
var error = {
|
||||
code: -32098,
|
||||
message: "XmlHttpRequestError " + errorThrown,
|
||||
|
@ -1310,7 +1281,7 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
|||
};
|
||||
deferred.reject(error, $.Event());
|
||||
});
|
||||
// Allow deferred user to disable on_rpc_error in fail
|
||||
// Allow deferred user to disable rpc_error call in fail
|
||||
deferred.fail(function() {
|
||||
deferred.fail(function(error, event) {
|
||||
if (!event.isDefaultPrevented()) {
|
||||
|
@ -1343,9 +1314,18 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
|||
// extracted from payload to set on the url
|
||||
var data = {
|
||||
session_id: this.session_id,
|
||||
id: payload.id
|
||||
id: payload.id,
|
||||
sid: this.httpsessionid,
|
||||
};
|
||||
url.url = this.get_url(url.url);
|
||||
|
||||
var set_sid = function (response, textStatus, jqXHR) {
|
||||
// If response give us the http session id, we store it for next requests...
|
||||
if (response.httpsessionid) {
|
||||
self.httpsessionid = response.httpsessionid;
|
||||
}
|
||||
};
|
||||
|
||||
url.url = this.url(url.url, null);
|
||||
var ajax = _.extend({
|
||||
type: "GET",
|
||||
dataType: 'jsonp',
|
||||
|
@ -1360,7 +1340,7 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
|||
if(payload_url.length < 2000) {
|
||||
// Direct jsonp request
|
||||
ajax.data.r = payload_str;
|
||||
return $.ajax(ajax);
|
||||
return $.ajax(ajax).done(set_sid);
|
||||
} else {
|
||||
// Indirect jsonp request
|
||||
var ifid = _.uniqueId('oe_rpc_iframe');
|
||||
|
@ -1387,21 +1367,31 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
|
|||
$iframe.unbind('load').bind('load', function() {
|
||||
$.ajax(ajax).always(function() {
|
||||
cleanUp();
|
||||
}).then(
|
||||
function() { deferred.resolve.apply(deferred, arguments); },
|
||||
function() { deferred.reject.apply(deferred, arguments); }
|
||||
);
|
||||
}).done(function() {
|
||||
deferred.resolve.apply(deferred, arguments);
|
||||
}).fail(function() {
|
||||
deferred.reject.apply(deferred, arguments);
|
||||
});
|
||||
});
|
||||
// now that the iframe can receive data, we fill and submit the form
|
||||
$form.submit();
|
||||
});
|
||||
// append the iframe to the DOM (will trigger the first load)
|
||||
$form.after($iframe);
|
||||
return deferred;
|
||||
return deferred.done(set_sid);
|
||||
}
|
||||
},
|
||||
get_url: function (file) {
|
||||
return this.prefix + file;
|
||||
|
||||
url: function(path, params) {
|
||||
var qs = '';
|
||||
if (!_.isNull(params)) {
|
||||
params = _.extend(params || {}, {session_id: this.session_id});
|
||||
if (this.httpsessionid) {
|
||||
params.sid = this.httpsessionid;
|
||||
}
|
||||
qs = '?' + $.param(params);
|
||||
}
|
||||
return this.prefix + path + qs;
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -3,10 +3,13 @@
|
|||
*--------------------------------------------------------*/
|
||||
var console;
|
||||
if (!console) {
|
||||
console = {log: function () {}};
|
||||
}
|
||||
if (!console.debug) {
|
||||
console.debug = console.log;
|
||||
// Even IE9 only exposes console object if debug window opened
|
||||
console = {};
|
||||
('log error debug info warn assert clear dir dirxml trace group'
|
||||
+ ' groupCollapsed groupEnd time timeEnd profile profileEnd count'
|
||||
+ ' exception').split(/\s+/).forEach(function(property) {
|
||||
console[property] = _.identity;
|
||||
});
|
||||
}
|
||||
|
||||
openerp.web.coresetup = function(instance) {
|
||||
|
@ -19,9 +22,9 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
this.name = instance._session_id;
|
||||
this.qweb_mutex = new $.Mutex();
|
||||
},
|
||||
rpc: function(url, params) {
|
||||
rpc: function(url, params, options) {
|
||||
params.session_id = this.session_id;
|
||||
return this._super(url, params);
|
||||
return this._super(url, params, options);
|
||||
},
|
||||
/**
|
||||
* Setup a sessionm
|
||||
|
@ -51,15 +54,15 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
var self = this;
|
||||
// TODO: session store in cookie should be optional
|
||||
this.session_id = this.get_cookie('session_id');
|
||||
return this.session_reload().pipe(function(result) {
|
||||
return this.session_reload().then(function(result) {
|
||||
var modules = instance._modules.join(',');
|
||||
var deferred = self.rpc('/web/webclient/qweblist', {mods: modules}).pipe(self.do_load_qweb);
|
||||
var deferred = self.rpc('/web/webclient/qweblist', {mods: modules}).then(self.load_qweb.bind(self));
|
||||
if(self.session_is_valid()) {
|
||||
return deferred.pipe(function() { return self.load_modules(); });
|
||||
return deferred.then(function() { return self.load_modules(); });
|
||||
}
|
||||
return $.when(
|
||||
deferred,
|
||||
self.rpc('/web/webclient/bootstrap_translations', {mods: instance._modules}).pipe(function(trans) {
|
||||
self.rpc('/web/webclient/bootstrap_translations', {mods: instance._modules}).then(function(trans) {
|
||||
instance.web._t.database.set_bundle(trans);
|
||||
})
|
||||
);
|
||||
|
@ -73,7 +76,7 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
*/
|
||||
session_reload: function () {
|
||||
var self = this;
|
||||
return this.rpc("/web/session/get_session_info", {}).then(function(result) {
|
||||
return this.rpc("/web/session/get_session_info", {}).done(function(result) {
|
||||
// If immediately follows a login (triggered by trying to restore
|
||||
// an invalid session or no session at all), refresh session data
|
||||
// (should not change, but just in case...)
|
||||
|
@ -96,7 +99,7 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
var self = this;
|
||||
var base_location = document.location.protocol + '//' + document.location.host;
|
||||
var params = { db: db, login: login, password: password, base_location: base_location };
|
||||
return this.rpc("/web/session/authenticate", params).pipe(function(result) {
|
||||
return this.rpc("/web/session/authenticate", params).then(function(result) {
|
||||
if (!result.uid) {
|
||||
return $.Deferred().reject();
|
||||
}
|
||||
|
@ -154,30 +157,28 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
*/
|
||||
load_modules: function() {
|
||||
var self = this;
|
||||
return this.rpc('/web/session/modules', {}).pipe(function(result) {
|
||||
var lang = self.user_context.lang,
|
||||
all_modules = _.uniq(self.module_list.concat(result));
|
||||
var params = { mods: all_modules, lang: lang};
|
||||
return this.rpc('/web/session/modules', {}).then(function(result) {
|
||||
var all_modules = _.uniq(self.module_list.concat(result));
|
||||
var to_load = _.difference(result, self.module_list).join(',');
|
||||
self.module_list = all_modules;
|
||||
|
||||
var loaded = self.rpc('/web/webclient/translations', params).then(function(trans) {
|
||||
instance.web._t.database.set_bundle(trans);
|
||||
});
|
||||
var file_list = ["/web/static/lib/datejs/globalization/" + lang.replace("_", "-") + ".js"];
|
||||
var loaded = self.load_translations();
|
||||
var datejs_locale = "/web/static/lib/datejs/globalization/" + self.user_context.lang.replace("_", "-") + ".js";
|
||||
|
||||
var file_list = [ datejs_locale ];
|
||||
if(to_load.length) {
|
||||
loaded = $.when(
|
||||
loaded,
|
||||
self.rpc('/web/webclient/csslist', {mods: to_load}).then(self.do_load_css),
|
||||
self.rpc('/web/webclient/qweblist', {mods: to_load}).pipe(self.do_load_qweb),
|
||||
self.rpc('/web/webclient/jslist', {mods: to_load}).then(function(files) {
|
||||
self.rpc('/web/webclient/csslist', {mods: to_load}).done(self.load_css.bind(self)),
|
||||
self.rpc('/web/webclient/qweblist', {mods: to_load}).then(self.load_qweb.bind(self)),
|
||||
self.rpc('/web/webclient/jslist', {mods: to_load}).done(function(files) {
|
||||
file_list = file_list.concat(files);
|
||||
})
|
||||
);
|
||||
}
|
||||
return loaded.pipe(function () {
|
||||
return self.do_load_js(file_list);
|
||||
}).then(function() {
|
||||
return loaded.then(function () {
|
||||
return self.load_js(file_list);
|
||||
}).done(function() {
|
||||
self.on_modules_loaded();
|
||||
self.trigger('module_loaded');
|
||||
if (!Date.CultureInfo.pmDesignator) {
|
||||
|
@ -190,29 +191,35 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
});
|
||||
});
|
||||
},
|
||||
do_load_css: function (files) {
|
||||
load_translations: function() {
|
||||
var params = { mods: this.module_list, lang: this.user_context.lang };
|
||||
return this.rpc('/web/webclient/translations', params).done(function(trans) {
|
||||
instance.web._t.database.set_bundle(trans);
|
||||
});
|
||||
},
|
||||
load_css: function (files) {
|
||||
var self = this;
|
||||
_.each(files, function (file) {
|
||||
$('head').append($('<link>', {
|
||||
'href': self.get_url(file),
|
||||
'href': self.url(file, null),
|
||||
'rel': 'stylesheet',
|
||||
'type': 'text/css'
|
||||
}));
|
||||
});
|
||||
},
|
||||
do_load_js: function(files) {
|
||||
load_js: function(files) {
|
||||
var self = this;
|
||||
var d = $.Deferred();
|
||||
if(files.length != 0) {
|
||||
if(files.length !== 0) {
|
||||
var file = files.shift();
|
||||
var tag = document.createElement('script');
|
||||
tag.type = 'text/javascript';
|
||||
tag.src = self.get_url(file);
|
||||
tag.src = self.url(file, null);
|
||||
tag.onload = tag.onreadystatechange = function() {
|
||||
if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done )
|
||||
return;
|
||||
tag.onload_done = true;
|
||||
self.do_load_js(files).then(function () {
|
||||
self.load_js(files).done(function () {
|
||||
d.resolve();
|
||||
});
|
||||
};
|
||||
|
@ -223,11 +230,11 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
|
|||
}
|
||||
return d;
|
||||
},
|
||||
do_load_qweb: function(files) {
|
||||
load_qweb: function(files) {
|
||||
var self = this;
|
||||
_.each(files, function(file) {
|
||||
self.qweb_mutex.exec(function() {
|
||||
return self.rpc('/web/proxy/load', {path: file}).pipe(function(xml) {
|
||||
return self.rpc('/web/proxy/load', {path: file}).then(function(xml) {
|
||||
if (!xml) { return; }
|
||||
instance.web.qweb.add_template(_.str.trim(xml));
|
||||
});
|
||||
|
@ -453,6 +460,16 @@ $.fn.getAttributes = function() {
|
|||
}
|
||||
return o;
|
||||
}
|
||||
$.fn.openerpClass = function(additionalClass) {
|
||||
// This plugin should be applied on top level elements
|
||||
additionalClass = additionalClass || '';
|
||||
if (!!$.browser.msie) {
|
||||
additionalClass += ' openerp_ie';
|
||||
}
|
||||
return this.each(function() {
|
||||
$(this).addClass('openerp ' + additionalClass);
|
||||
});
|
||||
};
|
||||
|
||||
/** Jquery extentions */
|
||||
$.Mutex = (function() {
|
||||
|
@ -462,7 +479,7 @@ $.Mutex = (function() {
|
|||
Mutex.prototype.exec = function(action) {
|
||||
var current = this.def;
|
||||
var next = this.def = $.Deferred();
|
||||
return current.pipe(function() {
|
||||
return current.then(function() {
|
||||
return $.when(action()).always(function() {
|
||||
next.resolve();
|
||||
});
|
||||
|
@ -474,7 +491,7 @@ $.Mutex = (function() {
|
|||
$.async_when = function() {
|
||||
var async = false;
|
||||
var def = $.Deferred();
|
||||
$.when.apply($, arguments).then(function() {
|
||||
$.when.apply($, arguments).done(function() {
|
||||
var args = arguments;
|
||||
var action = function() {
|
||||
def.resolve.apply(def, args);
|
||||
|
@ -483,7 +500,7 @@ $.async_when = function() {
|
|||
action();
|
||||
else
|
||||
setTimeout(action, 0);
|
||||
}, function() {
|
||||
}).fail(function() {
|
||||
var args = arguments;
|
||||
var action = function() {
|
||||
def.reject.apply(def, args);
|
||||
|
@ -530,7 +547,8 @@ instance.web.qweb.default_dict['__debug__'] = instance.session.debug; // Which o
|
|||
instance.web.qweb.debug = instance.session.debug;
|
||||
instance.web.qweb.default_dict = {
|
||||
'_' : _,
|
||||
'_t' : instance.web._t
|
||||
'_t' : instance.web._t,
|
||||
'JSON': JSON,
|
||||
};
|
||||
instance.web.qweb.preprocess_node = function() {
|
||||
// Note that 'this' is the Qweb Node
|
||||
|
|
|
@ -66,7 +66,7 @@ instance.web.Query = instance.web.Class.extend({
|
|||
offset: this._offset,
|
||||
limit: this._limit,
|
||||
sort: instance.web.serialize_sort(this._order_by)
|
||||
}).pipe(function (results) {
|
||||
}).then(function (results) {
|
||||
self._count = results.length;
|
||||
return results.records;
|
||||
}, null);
|
||||
|
@ -78,7 +78,7 @@ instance.web.Query = instance.web.Class.extend({
|
|||
*/
|
||||
first: function () {
|
||||
var self = this;
|
||||
return this.clone({limit: 1})._execute().pipe(function (records) {
|
||||
return this.clone({limit: 1})._execute().then(function (records) {
|
||||
delete self._count;
|
||||
if (records.length) { return records[0]; }
|
||||
return null;
|
||||
|
@ -132,9 +132,11 @@ instance.web.Query = instance.web.Class.extend({
|
|||
offset: this._offset,
|
||||
limit: this._limit,
|
||||
orderby: instance.web.serialize_sort(this._order_by) || false
|
||||
}).pipe(function (results) {
|
||||
}).then(function (results) {
|
||||
return _(results).map(function (result) {
|
||||
// FIX: querygroup initialization
|
||||
result.__context = result.__context || {};
|
||||
result.__context.group_by = result.__context.group_by || [];
|
||||
_.defaults(result.__context, ctx);
|
||||
return new instance.web.QueryGroup(
|
||||
self._model.name, grouping[0], result);
|
||||
|
@ -276,9 +278,10 @@ instance.web.Model = instance.web.Class.extend({
|
|||
* @param {String} method name of the method to call
|
||||
* @param {Array} [args] positional arguments
|
||||
* @param {Object} [kwargs] keyword arguments
|
||||
* @param {Object} [options] additional options for the rpc() method
|
||||
* @returns {jQuery.Deferred<>} call result
|
||||
*/
|
||||
call: function (method, args, kwargs) {
|
||||
call: function (method, args, kwargs, options) {
|
||||
args = args || [];
|
||||
kwargs = kwargs || {};
|
||||
if (!_.isArray(args)) {
|
||||
|
@ -292,7 +295,7 @@ instance.web.Model = instance.web.Class.extend({
|
|||
method: method,
|
||||
args: args,
|
||||
kwargs: kwargs
|
||||
});
|
||||
}, options);
|
||||
},
|
||||
/**
|
||||
* Fetches a Query instance bound to this model, for searching
|
||||
|
@ -356,17 +359,16 @@ instance.web.Model = instance.web.Class.extend({
|
|||
},
|
||||
});
|
||||
|
||||
instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
||||
instance.web.DataSet = instance.web.Class.extend(instance.web.PropertiesMixin, {
|
||||
/**
|
||||
* Collection of OpenERP records, used to share records and the current selection between views.
|
||||
*
|
||||
* @constructs instance.web.DataSet
|
||||
* @extends instance.web.CallbackEnabled
|
||||
*
|
||||
* @param {String} model the OpenERP model this dataset will manage
|
||||
*/
|
||||
init: function(parent, model, context) {
|
||||
this._super(parent);
|
||||
instance.web.PropertiesMixin.init.call(this);
|
||||
this.model = model;
|
||||
this.context = context || {};
|
||||
this.index = null;
|
||||
|
@ -441,7 +443,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
|||
return this._model.query(fields)
|
||||
.limit(options.limit || false)
|
||||
.offset(options.offset || 0)
|
||||
.all().then(function (records) {
|
||||
.all().done(function (records) {
|
||||
self.ids = _(records).pluck('id');
|
||||
});
|
||||
},
|
||||
|
@ -454,7 +456,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
|||
*/
|
||||
read_index: function (fields, options) {
|
||||
options = options || {};
|
||||
return this.read_ids([this.ids[this.index]], fields, options).pipe(function (records) {
|
||||
return this.read_ids([this.ids[this.index]], fields, options).then(function (records) {
|
||||
if (_.isEmpty(records)) { return $.Deferred().reject().promise(); }
|
||||
return records[0];
|
||||
});
|
||||
|
@ -469,7 +471,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
|||
default_get: function(fields, options) {
|
||||
options = options || {};
|
||||
return this._model.call('default_get',
|
||||
[fields], {context: this._model.context(options.context)});
|
||||
[fields], {context: this.get_context(options.context)});
|
||||
},
|
||||
/**
|
||||
* Creates a new record in db
|
||||
|
@ -478,7 +480,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
|||
* @returns {$.Deferred}
|
||||
*/
|
||||
create: function(data) {
|
||||
return this._model.call('create', [data], {context: this._model.context()});
|
||||
return this._model.call('create', [data], {context: this.get_context()});
|
||||
},
|
||||
/**
|
||||
* Saves the provided data in an existing db record
|
||||
|
@ -491,7 +493,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
|||
*/
|
||||
write: function (id, data, options) {
|
||||
options = options || {};
|
||||
return this._model.call('write', [[id], data], {context: this._model.context(options.context)}).then(this.trigger('dataset_changed', id, data, options));
|
||||
return this._model.call('write', [[id], data], {context: this.get_context(options.context)}).done(this.trigger('dataset_changed', id, data, options));
|
||||
},
|
||||
/**
|
||||
* Deletes an existing record from the database
|
||||
|
@ -499,7 +501,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
|||
* @param {Number|String} ids identifier of the record to delete
|
||||
*/
|
||||
unlink: function(ids) {
|
||||
return this._model.call('unlink', [ids], {context: this._model.context()}).then(this.trigger('dataset_changed', ids));
|
||||
return this._model.call('unlink', [ids], {context: this.get_context()}).done(this.trigger('dataset_changed', ids));
|
||||
},
|
||||
/**
|
||||
* Calls an arbitrary RPC method
|
||||
|
@ -530,7 +532,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
|||
* @returns {$.Deferred}
|
||||
*/
|
||||
name_get: function(ids) {
|
||||
return this._model.call('name_get', [ids], {context: this._model.context()});
|
||||
return this._model.call('name_get', [ids], {context: this.get_context()});
|
||||
},
|
||||
/**
|
||||
*
|
||||
|
@ -554,11 +556,10 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
|||
* @param name
|
||||
*/
|
||||
name_create: function(name) {
|
||||
return this._model.call('name_create', [name], {context: this._model.context()});
|
||||
return this._model.call('name_create', [name], {context: this.get_context()});
|
||||
},
|
||||
exec_workflow: function (id, signal) {
|
||||
return this._model.exec_workflow(id, signal)
|
||||
.pipe(function (result) { return { result: result }; });
|
||||
return this._model.exec_workflow(id, signal);
|
||||
},
|
||||
get_context: function(request_context) {
|
||||
return this._model.context(request_context);
|
||||
|
@ -605,8 +606,8 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({
|
|||
return instance.session.rpc('/web/dataset/resequence', {
|
||||
model: this.model,
|
||||
ids: ids,
|
||||
context: this._model.context(options.context),
|
||||
}).pipe(function (results) {
|
||||
context: this.get_context(options.context),
|
||||
}).then(function (results) {
|
||||
return results;
|
||||
});
|
||||
},
|
||||
|
@ -681,9 +682,9 @@ instance.web.DataSetSearch = instance.web.DataSet.extend({
|
|||
.limit(options.limit || false);
|
||||
q = q.order_by.apply(q, this._sort);
|
||||
|
||||
return q.all().then(function (records) {
|
||||
return q.all().done(function (records) {
|
||||
// FIXME: not sure about that one, *could* have discarded count
|
||||
q.count().then(function (count) { self._length = count; });
|
||||
q.count().done(function (count) { self._length = count; });
|
||||
self.ids = _(records).pluck('id');
|
||||
});
|
||||
},
|
||||
|
@ -692,7 +693,7 @@ instance.web.DataSetSearch = instance.web.DataSet.extend({
|
|||
},
|
||||
unlink: function(ids, callback, error_callback) {
|
||||
var self = this;
|
||||
return this._super(ids).then(function(result) {
|
||||
return this._super(ids).done(function(result) {
|
||||
self.ids = _(self.ids).difference(ids);
|
||||
if (self._length) {
|
||||
self._length -= 1;
|
||||
|
@ -721,10 +722,10 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({
|
|||
this.last_default_get = {};
|
||||
},
|
||||
default_get: function(fields, options) {
|
||||
return this._super(fields, options).then(this.on_default_get);
|
||||
},
|
||||
on_default_get: function(res) {
|
||||
this.last_default_get = res;
|
||||
var self = this;
|
||||
return this._super(fields, options).done(function(res) {
|
||||
self.last_default_get = res;
|
||||
});
|
||||
},
|
||||
create: function(data) {
|
||||
var cached = {id:_.uniqueId(this.virtual_id_prefix), values: data,
|
||||
|
@ -773,7 +774,7 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({
|
|||
this.cache = _.reject(this.cache, function(x) { return _.include(ids, x.id);});
|
||||
this.set_ids(_.without.apply(_, [this.ids].concat(ids)));
|
||||
this.trigger("dataset_changed", ids, callback, error_callback);
|
||||
return $.async_when({result: true}).then(callback);
|
||||
return $.async_when({result: true}).done(callback);
|
||||
},
|
||||
reset_ids: function(ids) {
|
||||
this.set_ids(ids);
|
||||
|
@ -835,7 +836,7 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({
|
|||
completion.resolve(records);
|
||||
};
|
||||
if(to_get.length > 0) {
|
||||
var rpc_promise = this._super(to_get, fields, options).then(function(records) {
|
||||
var rpc_promise = this._super(to_get, fields, options).done(function(records) {
|
||||
_.each(records, function(record, index) {
|
||||
var id = to_get[index];
|
||||
var cached = _.detect(self.cache, function(x) {return x.id === id;});
|
||||
|
@ -990,14 +991,14 @@ instance.web.DropMisordered = instance.web.Class.extend({
|
|||
var res = $.Deferred();
|
||||
|
||||
var self = this, seq = this.lsn++;
|
||||
deferred.then(function () {
|
||||
deferred.done(function () {
|
||||
if (seq > self.rsn) {
|
||||
self.rsn = seq;
|
||||
res.resolve.apply(res, arguments);
|
||||
} else if (self.failMisordered) {
|
||||
res.reject();
|
||||
}
|
||||
}, function () {
|
||||
}).fail(function () {
|
||||
res.reject.apply(res, arguments);
|
||||
});
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
self.rpc("/web/export/get_fields", {
|
||||
model: self.dataset.model,
|
||||
import_compat: Boolean(import_comp)
|
||||
}).then(function (records) {
|
||||
}).done(function (records) {
|
||||
got_fields.resolve();
|
||||
self.on_show_data(records);
|
||||
});
|
||||
|
@ -59,7 +59,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
|
||||
return $.when(
|
||||
got_fields,
|
||||
this.rpc('/web/export/formats', {}).then(this.do_setup_export_formats),
|
||||
this.rpc('/web/export/formats', {}).done(this.do_setup_export_formats),
|
||||
this.show_exports_list());
|
||||
},
|
||||
do_setup_export_formats: function (formats) {
|
||||
|
@ -84,7 +84,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
}
|
||||
return this.exports.read_slice(['name'], {
|
||||
domain: [['resource', '=', this.dataset.model]]
|
||||
}).then(function (export_list) {
|
||||
}).done(function (export_list) {
|
||||
if (!export_list.length) {
|
||||
return;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
self.$el.find('#fields_list option').remove();
|
||||
var export_id = self.$el.find('#saved_export_list option:selected').val();
|
||||
if (export_id) {
|
||||
self.rpc('/web/export/namelist', {'model': self.dataset.model, export_id: parseInt(export_id)}).then(self.do_load_export_field);
|
||||
self.rpc('/web/export/namelist', {'model': self.dataset.model, export_id: parseInt(export_id)}).done(self.do_load_export_field);
|
||||
}
|
||||
});
|
||||
self.$el.find('#delete_export_list').click(function() {
|
||||
|
@ -183,7 +183,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
import_compat: Boolean(import_comp),
|
||||
parent_field_type : record['field_type'],
|
||||
exclude: exclude_fields
|
||||
}).then(function(results) {
|
||||
}).done(function(results) {
|
||||
record.loaded = true;
|
||||
self.on_show_data(results, record.id);
|
||||
});
|
||||
|
|
|
@ -83,6 +83,42 @@ instance.web.strip_raw_chars = function (value) {
|
|||
var normalize_format = function (format) {
|
||||
return Date.normalizeFormat(instance.web.strip_raw_chars(format));
|
||||
};
|
||||
|
||||
/**
|
||||
* Check with a scary heuristic if the value is a bin_size or not.
|
||||
* If not, compute an approximate size out of the base64 encoded string.
|
||||
*
|
||||
* @param {String} value original format
|
||||
*/
|
||||
instance.web.binary_to_binsize = function (value) {
|
||||
if (!value) {
|
||||
return instance.web.human_size(0);
|
||||
}
|
||||
if (value.substr(0, 10).indexOf(' ') == -1) {
|
||||
// Computing approximate size out of base64 encoded string
|
||||
// http://en.wikipedia.org/wiki/Base64#MIME
|
||||
return instance.web.human_size(value.length / 1.37);
|
||||
} else {
|
||||
// already bin_size
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a human readable size
|
||||
*
|
||||
* @param {Number} numner of bytes
|
||||
*/
|
||||
instance.web.human_size = function(size) {
|
||||
var units = _t("Bytes,Kb,Mb,Gb,Tb,Pb,Eb,Zb,Yb").split(',');
|
||||
var i = 0;
|
||||
while (size >= 1024) {
|
||||
size /= 1024;
|
||||
++i;
|
||||
}
|
||||
return size.toFixed(2) + ' ' + units[i];
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a single atomic value based on a field descriptor
|
||||
*
|
||||
|
|
|
@ -124,19 +124,10 @@ function assert(condition, message) {
|
|||
}
|
||||
my.InputView = instance.web.Widget.extend({
|
||||
template: 'SearchView.InputView',
|
||||
start: function () {
|
||||
var p = this._super.apply(this, arguments);
|
||||
this.$el.on('focus', this.proxy('onFocus'));
|
||||
this.$el.on('blur', this.proxy('onBlur'));
|
||||
this.$el.on('keydown', this.proxy('onKeydown'));
|
||||
return p;
|
||||
},
|
||||
onFocus: function () {
|
||||
this.trigger('focused', this);
|
||||
},
|
||||
onBlur: function () {
|
||||
this.$el.text('');
|
||||
this.trigger('blurred', this);
|
||||
events: {
|
||||
focus: function () { this.trigger('focused', this); },
|
||||
blur: function () { this.$el.text(''); this.trigger('blurred', this); },
|
||||
keydown: 'onKeydown'
|
||||
},
|
||||
getSelection: function () {
|
||||
// get Text node
|
||||
|
@ -212,6 +203,27 @@ my.InputView = instance.web.Widget.extend({
|
|||
});
|
||||
my.FacetView = instance.web.Widget.extend({
|
||||
template: 'SearchView.FacetView',
|
||||
events: {
|
||||
'focus': function () { this.trigger('focused', this); },
|
||||
'blur': function () { this.trigger('blurred', this); },
|
||||
'click': function (e) {
|
||||
if ($(e.target).is('.oe_facet_remove')) {
|
||||
this.model.destroy();
|
||||
return false;
|
||||
}
|
||||
this.$el.focus();
|
||||
e.stopPropagation();
|
||||
},
|
||||
'keydown': function (e) {
|
||||
var keys = $.ui.keyCode;
|
||||
switch (e.which) {
|
||||
case keys.BACKSPACE:
|
||||
case keys.DELETE:
|
||||
this.model.destroy();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
init: function (parent, model) {
|
||||
this._super(parent);
|
||||
this.model = model;
|
||||
|
@ -223,33 +235,11 @@ my.FacetView = instance.web.Widget.extend({
|
|||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
this.$el.on('focus', function () { self.trigger('focused', self); });
|
||||
this.$el.on('blur', function () { self.trigger('blurred', self); });
|
||||
this.$el.on('click', function (e) {
|
||||
if ($(e.target).is('.oe_facet_remove')) {
|
||||
self.model.destroy();
|
||||
return false;
|
||||
}
|
||||
self.$el.focus();
|
||||
e.stopPropagation();
|
||||
});
|
||||
this.$el.on('keydown', function (e) {
|
||||
var keys = $.ui.keyCode;
|
||||
switch (e.which) {
|
||||
case keys.BACKSPACE:
|
||||
case keys.DELETE:
|
||||
self.model.destroy();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
var $e = self.$el.find('> span:last-child');
|
||||
var q = $.when(this._super());
|
||||
return q.pipe(function () {
|
||||
var values = self.model.values.map(function (value) {
|
||||
var $e = this.$('> span:last-child');
|
||||
return $.when(this._super()).then(function () {
|
||||
return $.when.apply(null, self.model.values.map(function (value) {
|
||||
return new my.FacetValueView(self, value).appendTo($e);
|
||||
});
|
||||
|
||||
return $.when.apply(null, values);
|
||||
}));
|
||||
});
|
||||
},
|
||||
model_changed: function () {
|
||||
|
@ -274,6 +264,39 @@ my.FacetValueView = instance.web.Widget.extend({
|
|||
|
||||
instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.SearchView# */{
|
||||
template: "SearchView",
|
||||
events: {
|
||||
// focus last input if view itself is clicked
|
||||
'click': function (e) {
|
||||
if (e.target === this.$('.oe_searchview_facets')[0]) {
|
||||
this.$('.oe_searchview_input:last').focus();
|
||||
}
|
||||
},
|
||||
// search button
|
||||
'click button.oe_searchview_search': function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
this.do_search();
|
||||
},
|
||||
'click .oe_searchview_clear': function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
this.query.reset();
|
||||
},
|
||||
'click .oe_searchview_unfold_drawer': function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
this.$el.toggleClass('oe_searchview_open_drawer');
|
||||
},
|
||||
'keydown .oe_searchview_input, .oe_searchview_facet': function (e) {
|
||||
switch(e.which) {
|
||||
case $.ui.keyCode.LEFT:
|
||||
this.focusPreceding(this);
|
||||
e.preventDefault();
|
||||
break;
|
||||
case $.ui.keyCode.RIGHT:
|
||||
this.focusFollowing(this);
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @constructs instance.web.SearchView
|
||||
* @extends instance.web.Widget
|
||||
|
@ -324,62 +347,18 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
context: this.dataset.get_context() });
|
||||
|
||||
$.when(load_view)
|
||||
.pipe(function(r) {
|
||||
.then(function(r) {
|
||||
self.search_view_loaded(r)
|
||||
}).fail(function () {
|
||||
}, function () {
|
||||
self.ready.reject.apply(null, arguments);
|
||||
});
|
||||
}
|
||||
|
||||
// Launch a search on clicking the oe_searchview_search button
|
||||
this.$el.on('click', 'button.oe_searchview_search', function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
self.do_search();
|
||||
});
|
||||
|
||||
this.$el.on('keydown',
|
||||
'.oe_searchview_input, .oe_searchview_facet', function (e) {
|
||||
switch(e.which) {
|
||||
case $.ui.keyCode.LEFT:
|
||||
self.focusPreceding(this);
|
||||
e.preventDefault();
|
||||
break;
|
||||
case $.ui.keyCode.RIGHT:
|
||||
self.focusFollowing(this);
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
this.$el.on('click', '.oe_searchview_clear', function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
self.query.reset();
|
||||
});
|
||||
this.$el.on('click', '.oe_searchview_unfold_drawer', function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
self.$el.toggleClass('oe_searchview_open_drawer');
|
||||
});
|
||||
instance.web.bus.on('click', this, function(ev) {
|
||||
if ($(ev.target).parents('.oe_searchview').length === 0) {
|
||||
self.$el.removeClass('oe_searchview_open_drawer');
|
||||
}
|
||||
});
|
||||
// Focus last input if the view itself is clicked (empty section of
|
||||
// facets element)
|
||||
this.$el.on('click', function (e) {
|
||||
if (e.target === self.$el.find('.oe_searchview_facets')[0]) {
|
||||
self.$el.find('.oe_searchview_input:last').focus();
|
||||
}
|
||||
});
|
||||
// when the completion list opens/refreshes, automatically select the
|
||||
// first completion item so if the user just hits [RETURN] or [TAB] it
|
||||
// automatically selects it
|
||||
this.$el.on('autocompleteopen', function () {
|
||||
var menu = self.$el.data('autocomplete').menu;
|
||||
menu.activate(
|
||||
$.Event({ type: "mouseenter" }),
|
||||
menu.element.children().first());
|
||||
});
|
||||
|
||||
return $.when(p, this.ready);
|
||||
},
|
||||
|
@ -429,58 +408,46 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
setup_global_completion: function () {
|
||||
var self = this;
|
||||
|
||||
// autocomplete only correctly handles being initialized on the actual
|
||||
// editable element (and only an element with a @value in 1.8 e.g.
|
||||
// input or textarea), cheat by setting val() on $el
|
||||
this.$el.on('keydown', function () {
|
||||
// keydown is triggered *before* the element's value is set, so
|
||||
// delay this. Pray that setTimeout are executed in FIFO (if they
|
||||
// have the same delay) as autocomplete uses the exact same trick.
|
||||
// FIXME: brittle as fuck
|
||||
setTimeout(function () {
|
||||
self.$el.val(self.currentInputValue());
|
||||
}, 0);
|
||||
|
||||
});
|
||||
|
||||
this.$el.autocomplete({
|
||||
var autocomplete = this.$el.autocomplete({
|
||||
source: this.proxy('complete_global_search'),
|
||||
select: this.proxy('select_completion'),
|
||||
focus: function (e) { e.preventDefault(); },
|
||||
html: true,
|
||||
autoFocus: true,
|
||||
minLength: 1,
|
||||
delay: 0
|
||||
}).data('autocomplete')._renderItem = function (ul, item) {
|
||||
// item of completion list
|
||||
var $item = $( "<li></li>" )
|
||||
.data( "item.autocomplete", item )
|
||||
.appendTo( ul );
|
||||
}).data('autocomplete');
|
||||
|
||||
if (item.facet !== undefined) {
|
||||
// regular completion item
|
||||
return $item.append(
|
||||
(item.label)
|
||||
? $('<a>').html(item.label)
|
||||
: $('<a>').text(item.value));
|
||||
}
|
||||
return $item.text(item.label)
|
||||
.css({
|
||||
borderTop: '1px solid #cccccc',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
zoom: 1,
|
||||
'float': 'left',
|
||||
clear: 'left',
|
||||
width: '100%'
|
||||
});
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Gets value out of the currently focused "input" (a
|
||||
* div[contenteditable].oe_searchview_input)
|
||||
*/
|
||||
currentInputValue: function () {
|
||||
return this.$el.find('div.oe_searchview_input:focus').text();
|
||||
// MonkeyPatch autocomplete instance
|
||||
_.extend(autocomplete, {
|
||||
_renderItem: function (ul, item) {
|
||||
// item of completion list
|
||||
var $item = $( "<li></li>" )
|
||||
.data( "item.autocomplete", item )
|
||||
.appendTo( ul );
|
||||
|
||||
if (item.facet !== undefined) {
|
||||
// regular completion item
|
||||
return $item.append(
|
||||
(item.label)
|
||||
? $('<a>').html(item.label)
|
||||
: $('<a>').text(item.value));
|
||||
}
|
||||
return $item.text(item.label)
|
||||
.css({
|
||||
borderTop: '1px solid #cccccc',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
zoom: 1,
|
||||
'float': 'left',
|
||||
clear: 'left',
|
||||
width: '100%'
|
||||
});
|
||||
},
|
||||
_value: function() {
|
||||
return self.$('div.oe_searchview_input').text();
|
||||
},
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Provide auto-completion result for req.term (an array to `resp`)
|
||||
|
@ -510,7 +477,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
|
||||
var input_index = _(this.input_subviews).indexOf(
|
||||
this.subviewForRoot(
|
||||
this.$el.find('div.oe_searchview_input:focus')[0]));
|
||||
this.$('div.oe_searchview_input:focus')[0]));
|
||||
this.query.add(ui.item.facet, {at: input_index / 2});
|
||||
},
|
||||
childFocused: function () {
|
||||
|
@ -539,7 +506,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
// _2: undefined if event=change, otherwise model
|
||||
var self = this;
|
||||
var started = [];
|
||||
var $e = this.$el.find('div.oe_searchview_facets');
|
||||
var $e = this.$('div.oe_searchview_facets');
|
||||
_.invoke(this.input_subviews, 'destroy');
|
||||
this.input_subviews = [];
|
||||
|
||||
|
@ -641,7 +608,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
// add Filters to this.inputs, need view.controls filled
|
||||
(new instance.web.search.Filters(this));
|
||||
// add custom filters to this.inputs
|
||||
(new instance.web.search.CustomFilters(this));
|
||||
this.custom_filters = new instance.web.search.CustomFilters(this);
|
||||
// add Advanced to this.inputs
|
||||
(new instance.web.search.Advanced(this));
|
||||
},
|
||||
|
@ -664,20 +631,45 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
// build drawer
|
||||
var drawer_started = $.when.apply(
|
||||
null, _(this.select_for_drawer()).invoke(
|
||||
'appendTo', this.$el.find('.oe_searchview_drawer')));
|
||||
'appendTo', this.$('.oe_searchview_drawer')));
|
||||
|
||||
// load defaults
|
||||
var defaults_fetched = $.when.apply(null, _(this.inputs).invoke(
|
||||
'facet_for_defaults', this.defaults)).then(function () {
|
||||
self.query.reset(_(arguments).compact(), {preventSearch: true});
|
||||
});
|
||||
|
||||
'facet_for_defaults', this.defaults))
|
||||
.then(this.proxy('setup_default_query'));
|
||||
|
||||
return $.when(drawer_started, defaults_fetched)
|
||||
.then(function () {
|
||||
.done(function () {
|
||||
self.trigger("search_view_loaded", data);
|
||||
self.ready.resolve();
|
||||
});
|
||||
},
|
||||
setup_default_query: function () {
|
||||
// Hacky implementation of CustomFilters#facet_for_defaults ensure
|
||||
// CustomFilters will be ready (and CustomFilters#filters will be
|
||||
// correctly filled) by the time this method executes.
|
||||
var custom_filters = this.custom_filters.filters;
|
||||
if (!_(custom_filters).isEmpty()) {
|
||||
// Check for any is_default custom filter
|
||||
var personal_filter = _(custom_filters).find(function (filter) {
|
||||
return filter.user_id && filter.is_default;
|
||||
});
|
||||
if (personal_filter) {
|
||||
this.custom_filters.enable_filter(personal_filter, true);
|
||||
return;
|
||||
}
|
||||
|
||||
var global_filter = _(custom_filters).find(function (filter) {
|
||||
return !filter.user_id && filter.is_default;
|
||||
});
|
||||
if (global_filter) {
|
||||
this.custom_filters.enable_filter(global_filter, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// No custom filter, or no is_default custom filter, apply view defaults
|
||||
this.query.reset(_(arguments).compact(), {preventSearch: true});
|
||||
},
|
||||
/**
|
||||
* Extract search data from the view's facets.
|
||||
*
|
||||
|
@ -736,6 +728,9 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
*
|
||||
* If at least one field failed its validation, triggers
|
||||
* :js:func:`instance.web.SearchView.on_invalid` instead.
|
||||
*
|
||||
* @param [_query]
|
||||
* @param {Object} [options]
|
||||
*/
|
||||
do_search: function (_query, options) {
|
||||
if (options && options.preventSearch) {
|
||||
|
@ -788,6 +783,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
instance.web.search.fields = new instance.web.Registry({
|
||||
'char': 'instance.web.search.CharField',
|
||||
'text': 'instance.web.search.CharField',
|
||||
'html': 'instance.web.search.CharField',
|
||||
'boolean': 'instance.web.search.BooleanField',
|
||||
'integer': 'instance.web.search.IntegerField',
|
||||
'id': 'instance.web.search.IntegerField',
|
||||
|
@ -960,7 +956,7 @@ instance.web.search.FilterGroup = instance.web.search.Input.extend(/** @lends in
|
|||
*/
|
||||
search_change: function () {
|
||||
var self = this;
|
||||
var $filters = this.$el.find('> li').removeClass('oe_selected');
|
||||
var $filters = this.$('> li').removeClass('oe_selected');
|
||||
var facet = this.view.query.find(_.bind(this.match_facet, this));
|
||||
if (!facet) { return; }
|
||||
facet.values.each(function (v) {
|
||||
|
@ -1438,7 +1434,7 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
|||
name: needle,
|
||||
limit: 8,
|
||||
context: {}
|
||||
}).pipe(function (results) {
|
||||
}).then(function (results) {
|
||||
if (_.isEmpty(results)) { return null; }
|
||||
return [{label: self.attrs.string}].concat(
|
||||
_(results).map(function (result) {
|
||||
|
@ -1461,7 +1457,7 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
|||
// to handle this as if it were a single value.
|
||||
value = value[0];
|
||||
}
|
||||
return this.model.call('name_get', [value]).pipe(function (names) {
|
||||
return this.model.call('name_get', [value]).then(function (names) {
|
||||
if (_(names).isEmpty()) { return null; }
|
||||
return facet_from(self, names[0]);
|
||||
})
|
||||
|
@ -1489,10 +1485,15 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
|||
instance.web.search.CustomFilters = instance.web.search.Input.extend({
|
||||
template: 'SearchView.CustomFilters',
|
||||
_in_drawer: true,
|
||||
init: function () {
|
||||
this.is_ready = $.Deferred();
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
this.model = new instance.web.Model('ir.filters');
|
||||
this.filters = {};
|
||||
this.$filters = {};
|
||||
this.view.query
|
||||
.on('remove', function (facet) {
|
||||
if (!facet.get('is_custom_filter')) {
|
||||
|
@ -1508,65 +1509,116 @@ instance.web.search.CustomFilters = instance.web.search.Input.extend({
|
|||
// FIXME: local eval of domain and context to get rid of special endpoint
|
||||
return this.rpc('/web/searchview/get_filters', {
|
||||
model: this.view.model
|
||||
}).pipe(this.proxy('set_filters'));
|
||||
})
|
||||
.then(this.proxy('set_filters'))
|
||||
.then(function () {
|
||||
self.is_ready.resolve(null);
|
||||
}, function () {
|
||||
self.is_ready.reject();
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Special implementation delaying defaults until CustomFilters is loaded
|
||||
*/
|
||||
facet_for_defaults: function () {
|
||||
return this.is_ready;
|
||||
},
|
||||
/**
|
||||
* Generates a mapping key (in the filters and $filter mappings) for the
|
||||
* filter descriptor object provided (as returned by ``get_filters``).
|
||||
*
|
||||
* The mapping key is guaranteed to be unique for a given (user_id, name)
|
||||
* pair.
|
||||
*
|
||||
* @param {Object} filter
|
||||
* @param {String} filter.name
|
||||
* @param {Number|Pair<Number, String>} [filter.user_id]
|
||||
* @return {String} mapping key corresponding to the filter
|
||||
*/
|
||||
key_for: function (filter) {
|
||||
var user_id = filter.user_id;
|
||||
var uid = (user_id instanceof Array) ? user_id[0] : user_id;
|
||||
return _.str.sprintf('(%s)%s', uid, filter.name);
|
||||
},
|
||||
/**
|
||||
* Generates a :js:class:`~instance.web.search.Facet` descriptor from a
|
||||
* filter descriptor
|
||||
*
|
||||
* @param {Object} filter
|
||||
* @param {String} filter.name
|
||||
* @param {Object} [filter.context]
|
||||
* @param {Array} [filter.domain]
|
||||
* @return {Object}
|
||||
*/
|
||||
facet_for: function (filter) {
|
||||
return {
|
||||
category: _t("Custom Filter"),
|
||||
icon: 'M',
|
||||
field: {
|
||||
get_context: function () { return filter.context; },
|
||||
get_groupby: function () { return [filter.context]; },
|
||||
get_domain: function () { return filter.domain; }
|
||||
},
|
||||
is_custom_filter: true,
|
||||
values: [{label: filter.name, value: null}]
|
||||
};
|
||||
},
|
||||
clear_selection: function () {
|
||||
this.$el.find('li.oe_selected').removeClass('oe_selected');
|
||||
this.$('li.oe_selected').removeClass('oe_selected');
|
||||
},
|
||||
append_filter: function (filter) {
|
||||
var self = this;
|
||||
var key = _.str.sprintf('(%s)%s', filter.user_id, filter.name);
|
||||
var key = this.key_for(filter);
|
||||
|
||||
var $filter;
|
||||
if (key in this.filters) {
|
||||
$filter = this.filters[key];
|
||||
if (key in this.$filters) {
|
||||
$filter = this.$filters[key];
|
||||
} else {
|
||||
var id = filter.id;
|
||||
$filter = this.filters[key] = $('<li></li>')
|
||||
.appendTo(this.$el.find('.oe_searchview_custom_list'))
|
||||
this.filters[key] = filter;
|
||||
$filter = this.$filters[key] = $('<li></li>')
|
||||
.appendTo(this.$('.oe_searchview_custom_list'))
|
||||
.addClass(filter.user_id ? 'oe_searchview_custom_private'
|
||||
: 'oe_searchview_custom_public')
|
||||
.toggleClass('oe_searchview_custom_default', filter.is_default)
|
||||
.text(filter.name);
|
||||
|
||||
$('<a class="oe_searchview_custom_delete">x</a>')
|
||||
.click(function (e) {
|
||||
e.stopPropagation();
|
||||
self.model.call('unlink', [id]).then(function () {
|
||||
self.model.call('unlink', [id]).done(function () {
|
||||
$filter.remove();
|
||||
delete self.$filters[key];
|
||||
delete self.filters[key];
|
||||
});
|
||||
})
|
||||
.appendTo($filter);
|
||||
}
|
||||
|
||||
$filter.unbind('click').click(function () {
|
||||
self.view.query.reset([{
|
||||
category: _t("Custom Filter"),
|
||||
icon: 'M',
|
||||
field: {
|
||||
get_context: function () { return filter.context; },
|
||||
get_groupby: function () { return [filter.context]; },
|
||||
get_domain: function () { return filter.domain; }
|
||||
},
|
||||
is_custom_filter: true,
|
||||
values: [{label: filter.name, value: null}]
|
||||
}]);
|
||||
$filter.addClass('oe_selected');
|
||||
self.enable_filter(filter);
|
||||
});
|
||||
},
|
||||
enable_filter: function (filter, preventSearch) {
|
||||
this.view.query.reset([this.facet_for(filter)], {
|
||||
preventSearch: preventSearch || false});
|
||||
this.$filters[this.key_for(filter)].addClass('oe_selected');
|
||||
},
|
||||
set_filters: function (filters) {
|
||||
_(filters).map(_.bind(this.append_filter, this));
|
||||
},
|
||||
save_current: function () {
|
||||
var self = this;
|
||||
var $name = this.$el.find('input:first');
|
||||
var private_filter = !this.$el.find('input:last').prop('checked');
|
||||
var $name = this.$('input:first');
|
||||
var private_filter = !this.$('#oe_searchview_custom_public').prop('checked');
|
||||
var set_as_default = this.$('#oe_searchview_custom_default').prop('checked');
|
||||
|
||||
var search = this.view.build_search_data();
|
||||
this.rpc('/web/session/eval_domain_and_context', {
|
||||
domains: search.domains,
|
||||
contexts: search.contexts,
|
||||
group_by_seq: search.groupbys || []
|
||||
}).then(function (results) {
|
||||
}).done(function (results) {
|
||||
if (!_.isEmpty(results.group_by)) {
|
||||
results.context.group_by = results.group_by;
|
||||
}
|
||||
|
@ -1575,10 +1627,11 @@ instance.web.search.CustomFilters = instance.web.search.Input.extend({
|
|||
user_id: private_filter ? instance.session.uid : false,
|
||||
model_id: self.view.model,
|
||||
context: results.context,
|
||||
domain: results.domain
|
||||
domain: results.domain,
|
||||
is_default: set_as_default
|
||||
};
|
||||
// FIXME: current context?
|
||||
return self.model.call('create_or_replace', [filter]).then(function (id) {
|
||||
return self.model.call('create_or_replace', [filter]).done(function (id) {
|
||||
filter.id = id;
|
||||
self.append_filter(filter);
|
||||
self.$el
|
||||
|
@ -1655,20 +1708,29 @@ instance.web.search.Advanced = instance.web.search.Input.extend({
|
|||
});
|
||||
return $.when(
|
||||
this._super(),
|
||||
this.rpc("/web/searchview/fields_get", {model: this.view.model}).then(function(data) {
|
||||
this.rpc("/web/searchview/fields_get", {model: this.view.model}).done(function(data) {
|
||||
self.fields = _.extend({
|
||||
id: { string: 'ID', type: 'id' }
|
||||
}, data.fields);
|
||||
})).then(function () {
|
||||
})).done(function () {
|
||||
self.append_proposition();
|
||||
});
|
||||
},
|
||||
append_proposition: function () {
|
||||
var self = this;
|
||||
return (new instance.web.search.ExtendedSearchProposition(this, this.fields))
|
||||
.appendTo(this.$el.find('ul'));
|
||||
.appendTo(this.$('ul')).done(function () {
|
||||
self.$('button.oe_apply').prop('disabled', false);
|
||||
});
|
||||
},
|
||||
remove_proposition: function (prop) {
|
||||
// removing last proposition, disable apply button
|
||||
if (this.getChildren().length <= 1) {
|
||||
this.$('button.oe_apply').prop('disabled', true);
|
||||
}
|
||||
prop.destroy();
|
||||
},
|
||||
commit_search: function () {
|
||||
var self = this;
|
||||
// Get domain sections from all propositions
|
||||
var children = this.getChildren();
|
||||
var propositions = _.invoke(children, 'get_proposition');
|
||||
|
@ -1698,6 +1760,13 @@ instance.web.search.Advanced = instance.web.search.Input.extend({
|
|||
|
||||
instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @lends instance.web.search.ExtendedSearchProposition# */{
|
||||
template: 'SearchView.extended_search.proposition',
|
||||
events: {
|
||||
'change .searchview_extended_prop_field': 'changed',
|
||||
'click .searchview_extended_delete_prop': function (e) {
|
||||
e.stopPropagation();
|
||||
this.getParent().remove_proposition(this);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @constructs instance.web.search.ExtendedSearchProposition
|
||||
* @extends instance.web.Widget
|
||||
|
@ -1715,17 +1784,10 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @
|
|||
this.value = null;
|
||||
},
|
||||
start: function () {
|
||||
var _this = this;
|
||||
this.$el.find(".searchview_extended_prop_field").change(function() {
|
||||
_this.changed();
|
||||
});
|
||||
this.$el.find('.searchview_extended_delete_prop').click(function () {
|
||||
_this.destroy();
|
||||
});
|
||||
this.changed();
|
||||
return this._super().done(this.proxy('changed'));
|
||||
},
|
||||
changed: function() {
|
||||
var nval = this.$el.find(".searchview_extended_prop_field").val();
|
||||
var nval = this.$(".searchview_extended_prop_field").val();
|
||||
if(this.attrs.selected == null || nval != this.attrs.selected.name) {
|
||||
this.select_field(_.detect(this.fields, function(x) {return x.name == nval;}));
|
||||
}
|
||||
|
@ -1740,7 +1802,7 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @
|
|||
if(this.attrs.selected != null) {
|
||||
this.value.destroy();
|
||||
this.value = null;
|
||||
this.$el.find('.searchview_extended_prop_op').html('');
|
||||
this.$('.searchview_extended_prop_op').html('');
|
||||
}
|
||||
this.attrs.selected = field;
|
||||
if(field == null) {
|
||||
|
@ -1756,9 +1818,9 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @
|
|||
_.each(this.value.operators, function(operator) {
|
||||
$('<option>', {value: operator.value})
|
||||
.text(String(operator.text))
|
||||
.appendTo(self.$el.find('.searchview_extended_prop_op'));
|
||||
.appendTo(self.$('.searchview_extended_prop_op'));
|
||||
});
|
||||
var $value_loc = this.$el.find('.searchview_extended_prop_value').empty();
|
||||
var $value_loc = this.$('.searchview_extended_prop_value').empty();
|
||||
this.value.appendTo($value_loc);
|
||||
|
||||
},
|
||||
|
@ -1766,7 +1828,7 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @
|
|||
if ( this.attrs.selected == null)
|
||||
return null;
|
||||
var field = this.attrs.selected;
|
||||
var op = this.$el.find('.searchview_extended_prop_op')[0];
|
||||
var op = this.$('.searchview_extended_prop_op')[0];
|
||||
var operator = op.options[op.selectedIndex];
|
||||
return {
|
||||
label: _.str.sprintf(_t('%(field)s %(operator)s "%(value)s"'), {
|
||||
|
|
|
@ -32,20 +32,20 @@ openerp.test_support = {
|
|||
window.openerp.web[tested_core](oe);
|
||||
var done = openerp.test_support.setup_session(oe.session);
|
||||
if (nonliterals) {
|
||||
done = done.pipe(function () {
|
||||
done = done.then(function () {
|
||||
return oe.session.rpc('/tests/add_nonliterals', {
|
||||
domains: nonliterals.domains || [],
|
||||
contexts: nonliterals.contexts || []
|
||||
}).then(function (r) {
|
||||
}).done(function (r) {
|
||||
oe.domains = r.domains;
|
||||
oe.contexts = r.contexts;
|
||||
});
|
||||
});
|
||||
}
|
||||
done.always(QUnit.start)
|
||||
.then(function () {
|
||||
.done(function () {
|
||||
conf.openerp = oe;
|
||||
}, function (e) {
|
||||
}).fail(function (e) {
|
||||
QUnit.test(title, function () {
|
||||
console.error(e);
|
||||
QUnit.ok(false, 'Could not obtain a session:' + e.debug);
|
||||
|
|