[MERGE] all kinds of broken shit from trunk
bzr revid: xmo@openerp.com-20110726123626-l54udy078dwj9rjo
This commit is contained in:
@@ -3,4 +3,36 @@
|
||||
"version" : "2.0",
|
||||
"depends" : [],
|
||||
'active': True,
|
||||
'js' : [
|
||||
"static/lib/datejs/date-en-US.js",
|
||||
"static/lib/jquery/jquery-1.6.2.js",
|
||||
"static/lib/jquery.ba-bbq/jquery.ba-bbq.js",
|
||||
"static/lib/jquery.contextmenu/jquery.contextmenu.r2.packed.js",
|
||||
"static/lib/jquery.superfish/js/hoverIntent.js",
|
||||
"static/lib/jquery.superfish/js/superfish.js",
|
||||
"static/lib/jquery.ui/js/jquery-ui-1.8.9.custom.min.js",
|
||||
"static/lib/jquery.ui/js/jquery-ui-timepicker-addon.js",
|
||||
"static/lib/jquery.ui.notify/js/jquery.notify.js",
|
||||
"static/lib/json/json2.js",
|
||||
"static/lib/qweb/qweb2.js",
|
||||
"static/lib/underscore/underscore.js",
|
||||
"static/lib/underscore/underscore.string.js",
|
||||
"static/src/js/base.js",
|
||||
"static/src/js/chrome.js",
|
||||
"static/src/js/controller.js",
|
||||
"static/src/js/views.js",
|
||||
"static/src/js/data.js",
|
||||
"static/src/js/dates.js",
|
||||
"static/src/js/form.js",
|
||||
"static/src/js/list.js",
|
||||
"static/src/js/list-editable.js",
|
||||
"static/src/js/search.js",
|
||||
"static/src/js/view_tree.js",
|
||||
],
|
||||
'css' : [
|
||||
"static/lib/jquery.superfish/css/superfish.css",
|
||||
"static/lib/jquery.ui/css/smoothness/jquery-ui-1.8.9.custom.css",
|
||||
"static/lib/jquery.ui.notify/css/ui.notify.css",
|
||||
"static/src/css/base.css",
|
||||
],
|
||||
}
|
||||
|
||||
+174
-85
@@ -54,6 +54,99 @@ class Xml2Json:
|
||||
# OpenERP Web base Controllers
|
||||
#----------------------------------------------------------
|
||||
|
||||
def manifest_glob(addons, key):
|
||||
files = []
|
||||
for addon in addons:
|
||||
globlist = openerpweb.addons_manifest.get(addon, {}).get(key, [])
|
||||
print globlist
|
||||
for pattern in globlist:
|
||||
for path in glob.glob(os.path.join(openerpweb.path_addons, addon, pattern)):
|
||||
files.append(path[len(openerpweb.path_addons):])
|
||||
return files
|
||||
|
||||
def concat_files(file_list):
|
||||
""" Concatenate file content
|
||||
return (concat,timestamp)
|
||||
concat: concatenation of file content
|
||||
timestamp: max(os.path.getmtime of file_list)
|
||||
"""
|
||||
root = openerpweb.path_root
|
||||
files_content = []
|
||||
files_timestamp = 0
|
||||
for i in file_list:
|
||||
fname = os.path.join(root, i)
|
||||
ftime = os.path.getmtime(fname)
|
||||
if ftime > files_timestamp:
|
||||
files_timestamp = ftime
|
||||
files_content = open(fname).read()
|
||||
files_concat = "".join(files_content)
|
||||
return files_concat
|
||||
|
||||
class WebClient(openerpweb.Controller):
|
||||
_cp_path = "/base/webclient"
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def csslist(self, req, mods='base'):
|
||||
return manifest_glob(mods.split(','), 'css')
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def jslist(self, req, mods='base'):
|
||||
return manifest_glob(mods.split(','), 'js')
|
||||
|
||||
@openerpweb.httprequest
|
||||
def css(self, req, mods='base'):
|
||||
cherrypy.response.headers['Content-Type'] = 'text/css'
|
||||
files = manifest_glob(mods.split(','), 'css')
|
||||
concat = concat_files(files)[0]
|
||||
# TODO request set the Date of last modif and Etag
|
||||
return concat
|
||||
|
||||
@openerpweb.httprequest
|
||||
def js(self, req, mods='base'):
|
||||
cherrypy.response.headers['Content-Type'] = 'application/javascript'
|
||||
files = manifest_glob(mods.split(','), 'js')
|
||||
concat = concat_files(files)[0]
|
||||
# TODO request set the Date of last modif and Etag
|
||||
return concat
|
||||
|
||||
@openerpweb.httprequest
|
||||
def home(self, req):
|
||||
template ="""<!DOCTYPE html>
|
||||
<html style="height: 100%%">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>OpenERP</title>
|
||||
%s
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
QWeb = new QWeb2.Engine();
|
||||
openerp.init().base.webclient("oe");
|
||||
});
|
||||
</script>
|
||||
<link rel="shortcut icon" href="/base/static/src/img/favicon.ico" type="image/x-icon"/>
|
||||
%s
|
||||
<!--[if lte IE 7]>
|
||||
<link rel="stylesheet" href="/base/static/src/css/base-ie7.css" type="text/css"/>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body id="oe" class="openerp"></body>
|
||||
</html>
|
||||
""".replace('\n'+' '*8,'\n')
|
||||
|
||||
# script tags
|
||||
jslist = ['/base/webclient/js']
|
||||
if 1: # debug == 1
|
||||
jslist = manifest_glob(['base'], 'js')
|
||||
js = "\n ".join(['<script type="text/javascript" src="%s"></script>'%i for i in jslist])
|
||||
|
||||
# css tags
|
||||
csslist = ['/base/webclient/css']
|
||||
if 1: # debug == 1
|
||||
csslist = manifest_glob(['base'], 'css')
|
||||
css = "\n ".join(['<link rel="stylesheet" href="%s">'%i for i in csslist])
|
||||
r = template % (js, css)
|
||||
return r
|
||||
|
||||
class Database(openerpweb.Controller):
|
||||
_cp_path = "/base/database"
|
||||
|
||||
@@ -71,37 +164,6 @@ class Database(openerpweb.Controller):
|
||||
class Session(openerpweb.Controller):
|
||||
_cp_path = "/base/session"
|
||||
|
||||
def manifest_glob(self, addons, key):
|
||||
files = []
|
||||
for addon in addons:
|
||||
globlist = openerpweb.addons_manifest.get(addon, {}).get(key, [])
|
||||
|
||||
files.extend([
|
||||
resource_path[len(openerpweb.path_addons):]
|
||||
for pattern in globlist
|
||||
for resource_path in glob.glob(os.path.join(
|
||||
openerpweb.path_addons, addon, pattern))
|
||||
])
|
||||
return files
|
||||
|
||||
def concat_files(self, file_list):
|
||||
""" Concatenate file content
|
||||
return (concat,timestamp)
|
||||
concat: concatenation of file content
|
||||
timestamp: max(os.path.getmtime of file_list)
|
||||
"""
|
||||
root = openerpweb.path_root
|
||||
files_content = []
|
||||
files_timestamp = 0
|
||||
for i in file_list:
|
||||
fname = os.path.join(root, i)
|
||||
ftime = os.path.getmtime(fname)
|
||||
if ftime > files_timestamp:
|
||||
files_timestamp = ftime
|
||||
files_content = open(fname).read()
|
||||
files_concat = "".join(files_content)
|
||||
return files_concat
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def login(self, req, db, login, password):
|
||||
req.session.login(db, login, password)
|
||||
@@ -118,31 +180,12 @@ class Session(openerpweb.Controller):
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def modules(self, req):
|
||||
return {"modules": [name
|
||||
for name, manifest in openerpweb.addons_manifest.iteritems()
|
||||
if manifest.get('active', True)]}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def csslist(self, req, mods='base'):
|
||||
return {'files': self.manifest_glob(mods.split(','), 'css')}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def jslist(self, req, mods='base'):
|
||||
return {'files': self.manifest_glob(mods.split(','), 'js')}
|
||||
|
||||
def css(self, req, mods='base'):
|
||||
files = self.manifest_glob(mods.split(','), 'css')
|
||||
concat = self.concat_files(files)[0]
|
||||
# TODO request set the Date of last modif and Etag
|
||||
return concat
|
||||
css.exposed = True
|
||||
|
||||
def js(self, req, mods='base'):
|
||||
files = self.manifest_glob(mods.split(','), 'js')
|
||||
concat = self.concat_files(files)[0]
|
||||
# TODO request set the Date of last modif and Etag
|
||||
return concat
|
||||
js.exposed = True
|
||||
# TODO query server for installed web modules
|
||||
mods = []
|
||||
for name, manifest in openerpweb.addons_manifest.items():
|
||||
if name != 'base' and manifest.get('active', True):
|
||||
mods.append(name)
|
||||
return mods
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def eval_domain_and_context(self, req, contexts, domains,
|
||||
@@ -269,7 +312,7 @@ def clean_action(action, session):
|
||||
action['domain'] = eval(
|
||||
action['domain'],
|
||||
session.evaluation_context(
|
||||
action['context'])) or []
|
||||
action.get('context', {}))) or []
|
||||
if 'flags' not in action:
|
||||
# Set empty flags dictionary for web client.
|
||||
action['flags'] = dict()
|
||||
@@ -574,10 +617,15 @@ class View(openerpweb.Controller):
|
||||
else:
|
||||
xml = ElementTree.fromstring(arch)
|
||||
fvg['arch'] = Xml2Json.convert_element(xml)
|
||||
for field in fvg['fields'].values():
|
||||
if field.has_key('views') and field['views']:
|
||||
for view in field["views"].values():
|
||||
|
||||
for field in fvg['fields'].itervalues():
|
||||
if field.get('views'):
|
||||
for view in field["views"].itervalues():
|
||||
self.process_view(session, view, None, transform)
|
||||
if field.get('domain'):
|
||||
field["domain"] = self.parse_domain(field["domain"], session)
|
||||
if field.get('context'):
|
||||
field["context"] = self.parse_context(field["context"], session)
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def add_custom(self, request, view_id, arch):
|
||||
@@ -615,27 +663,38 @@ class View(openerpweb.Controller):
|
||||
self.parse_domains_and_contexts(elem, session)
|
||||
return root
|
||||
|
||||
def parse_domain(self, elem, attr_name, session):
|
||||
""" Parses an attribute of the provided name as a domain, transforms it
|
||||
def parse_domain(self, domain, session):
|
||||
""" Parses an arbitrary string containing a domain, transforms it
|
||||
to either a literal domain or a :class:`openerpweb.nonliterals.Domain`
|
||||
|
||||
:param elem: the node being parsed
|
||||
:type param: xml.etree.ElementTree.Element
|
||||
:param str attr_name: the name of the attribute which should be parsed
|
||||
:param domain: the domain to parse, if the domain is not a string it is assumed to
|
||||
be a literal domain and is returned as-is
|
||||
:param session: Current OpenERP session
|
||||
:type session: openerpweb.openerpweb.OpenERPSession
|
||||
"""
|
||||
domain = elem.get(attr_name, '').strip()
|
||||
if domain:
|
||||
try:
|
||||
elem.set(
|
||||
attr_name,
|
||||
openerpweb.ast.literal_eval(
|
||||
domain))
|
||||
except ValueError:
|
||||
# not a literal
|
||||
elem.set(attr_name,
|
||||
openerpweb.nonliterals.Domain(session, domain))
|
||||
if not isinstance(domain, (str, unicode)):
|
||||
return domain
|
||||
try:
|
||||
return openerpweb.ast.literal_eval(domain)
|
||||
except ValueError:
|
||||
# not a literal
|
||||
return openerpweb.nonliterals.Domain(session, domain)
|
||||
|
||||
def parse_context(self, context, session):
|
||||
""" Parses an arbitrary string containing a context, transforms it
|
||||
to either a literal context or a :class:`openerpweb.nonliterals.Context`
|
||||
|
||||
:param context: the context to parse, if the context is not a string it is assumed to
|
||||
be a literal domain and is returned as-is
|
||||
:param session: Current OpenERP session
|
||||
:type session: openerpweb.openerpweb.OpenERPSession
|
||||
"""
|
||||
if not isinstance(context, (str, unicode)):
|
||||
return context
|
||||
try:
|
||||
return openerpweb.ast.literal_eval(context)
|
||||
except ValueError:
|
||||
return openerpweb.nonliterals.Context(session, context)
|
||||
|
||||
def parse_domains_and_contexts(self, elem, session):
|
||||
""" Converts domains and contexts from the view into Python objects,
|
||||
@@ -648,18 +707,14 @@ class View(openerpweb.Controller):
|
||||
non-literal objects
|
||||
:type session: openerpweb.openerpweb.OpenERPSession
|
||||
"""
|
||||
self.parse_domain(elem, 'domain', session)
|
||||
self.parse_domain(elem, 'filter_domain', session)
|
||||
for el in ['domain', 'filter_domain']:
|
||||
domain = elem.get(el, '').strip()
|
||||
if domain:
|
||||
elem.set(el, self.parse_domain(domain, session))
|
||||
for el in ['context', 'default_get']:
|
||||
context_string = elem.get(el, '').strip()
|
||||
if context_string:
|
||||
try:
|
||||
elem.set(el,
|
||||
openerpweb.ast.literal_eval(context_string))
|
||||
except ValueError:
|
||||
elem.set(el,
|
||||
openerpweb.nonliterals.Context(
|
||||
session, context_string))
|
||||
elem.set(el, self.parse_context(context_string, session))
|
||||
|
||||
class FormView(View):
|
||||
_cp_path = "/base/formview"
|
||||
@@ -707,7 +762,41 @@ class SearchView(View):
|
||||
def fields_get(self, req, model):
|
||||
Model = req.session.model(model)
|
||||
fields = Model.fields_get(False, req.session.eval_context(req.context))
|
||||
for field in fields.values():
|
||||
# shouldn't convert the views too?
|
||||
if field.get('domain'):
|
||||
field["domain"] = self.parse_domain(field["domain"], req.session)
|
||||
if field.get('context'):
|
||||
field["context"] = self.parse_domain(field["context"], req.session)
|
||||
return {'fields': fields}
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def get_filters(self, req, model):
|
||||
Model = req.session.model("ir.filters")
|
||||
filters = Model.get_filters(model)
|
||||
for filter in filters:
|
||||
filter["context"] = req.session.eval_context(self.parse_context(filter["context"], req.session))
|
||||
filter["domain"] = req.session.eval_domain(self.parse_domain(filter["domain"], req.session))
|
||||
return filters
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def save_filter(self, req, model, name, context_to_save, domain):
|
||||
Model = req.session.model("ir.filters")
|
||||
ctx = openerpweb.nonliterals.CompoundContext(context_to_save)
|
||||
ctx.session = req.session
|
||||
ctx = ctx.evaluate()
|
||||
domain = openerpweb.nonliterals.CompoundDomain(domain)
|
||||
domain.session = req.session
|
||||
domain = domain.evaluate()
|
||||
uid = req.session._uid
|
||||
context = req.session.eval_context(req.context)
|
||||
to_return = Model.create_or_replace({"context": ctx,
|
||||
"domain": domain,
|
||||
"model_id": model,
|
||||
"name": name,
|
||||
"user_id": uid
|
||||
}, context)
|
||||
return to_return
|
||||
|
||||
class Binary(openerpweb.Controller):
|
||||
_cp_path = "/base/binary"
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
/*! LAB.js (LABjs :: Loading And Blocking JavaScript)
|
||||
v1.2.0 (c) Kyle Simpson
|
||||
MIT License
|
||||
*/
|
||||
(function(p){var q="string",w="head",L="body",M="script",u="readyState",j="preloaddone",x="loadtrigger",N="srcuri",E="preload",Z="complete",y="done",z="which",O="preserve",F="onreadystatechange",ba="onload",P="hasOwnProperty",bb="script/cache",Q="[object ",bw=Q+"Function]",bx=Q+"Array]",e=null,h=true,i=false,k=p.document,bc=p.location,bd=p.ActiveXObject,A=p.setTimeout,be=p.clearTimeout,R=function(a){return k.getElementsByTagName(a)},S=Object.prototype.toString,G=function(){},r={},T={},bf=/^[^?#]*\//.exec(bc.href)[0],bg=/^\w+\:\/\/\/?[^\/]+/.exec(bf)[0],by=R(M),bh=p.opera&&S.call(p.opera)==Q+"Opera]",bi=("MozAppearance"in k.documentElement.style),bj=(k.createElement(M).async===true),v={cache:!(bi||bh),order:bi||bh||bj,xhr:h,dupe:h,base:"",which:w};v[O]=i;v[E]=h;r[w]=k.head||R(w);r[L]=R(L);function B(a){return S.call(a)===bw}function U(a,b){var c=/^\w+\:\/\//,d;if(typeof a!=q)a="";if(typeof b!=q)b="";d=((/^\/\//.test(a))?bc.protocol:"")+a;d=(c.test(d)?"":b)+d;return((c.test(d)?"":(d.charAt(0)==="/"?bg:bf))+d)}function bz(a){return(U(a).indexOf(bg)===0)}function bA(a){var b,c=-1;while(b=by[++c]){if(typeof b.src==q&&a===U(b.src)&&b.type!==bb)return h}return i}function H(t,l){t=!(!t);if(l==e)l=v;var bk=i,C=t&&l[E],bl=C&&l.cache,I=C&&l.order,bm=C&&l.xhr,bB=l[O],bC=l.which,bD=l.base,bn=G,J=i,D,s=h,m={},K=[],V=e;C=bl||bm||I;function bo(a,b){if((a[u]&&a[u]!==Z&&a[u]!=="loaded")||b[y]){return i}a[ba]=a[F]=e;return h}function W(a,b,c){c=!(!c);if(!c&&!(bo(a,b)))return;b[y]=h;for(var d in m){if(m[P](d)&&!(m[d][y]))return}bk=h;bn()}function bp(a){if(B(a[x])){a[x]();a[x]=e}}function bE(a,b){if(!bo(a,b))return;b[j]=h;A(function(){r[b[z]].removeChild(a);bp(b)},0)}function bF(a,b){if(a[u]===4){a[F]=G;b[j]=h;A(function(){bp(b)},0)}}function X(b,c,d,g,f,n){var o=b[z];A(function(){if("item"in r[o]){if(!r[o][0]){A(arguments.callee,25);return}r[o]=r[o][0]}var a=k.createElement(M);if(typeof d==q)a.type=d;if(typeof g==q)a.charset=g;if(B(f)){a[ba]=a[F]=function(){f(a,b)};a.src=c;if(bj){a.async=i}}r[o].insertBefore(a,(o===w?r[o].firstChild:e));if(typeof n==q){a.text=n;W(a,b,h)}},0)}function bq(a,b,c,d){T[a[N]]=h;X(a,b,c,d,W)}function br(a,b,c,d){var g=arguments;if(s&&a[j]==e){a[j]=i;X(a,b,bb,d,bE)}else if(!s&&a[j]!=e&&!a[j]){a[x]=function(){br.apply(e,g)}}else if(!s){bq.apply(e,g)}}function bs(a,b,c,d){var g=arguments,f;if(s&&a[j]==e){a[j]=i;f=a.xhr=(bd?new bd("Microsoft.XMLHTTP"):new p.XMLHttpRequest());f[F]=function(){bF(f,a)};f.open("GET",b);f.send("")}else if(!s&&a[j]!=e&&!a[j]){a[x]=function(){bs.apply(e,g)}}else if(!s){T[a[N]]=h;X(a,b,c,d,e,a.xhr.responseText);a.xhr=e}}function bt(a){if(typeof a=="undefined"||!a)return;if(a.allowDup==e)a.allowDup=l.dupe;var b=a.src,c=a.type,d=a.charset,g=a.allowDup,f=U(b,bD),n,o=bz(f);if(typeof d!=q)d=e;g=!(!g);if(!g&&((T[f]!=e)||(s&&m[f])||bA(f))){if(m[f]!=e&&m[f][j]&&!m[f][y]&&o){W(e,m[f],h)}return}if(m[f]==e)m[f]={};n=m[f];if(n[z]==e)n[z]=bC;n[y]=i;n[N]=f;J=h;if(!I&&bm&&o)bs(n,f,c,d);else if(!I&&bl)br(n,f,c,d);else bq(n,f,c,d)}function Y(a){if(t&&!I)K.push(a);if(!t||C)a()}function bu(a){var b=[],c;for(c=-1;++c<a.length;){if(S.call(a[c])===bx)b=b.concat(bu(a[c]));else b[b.length]=a[c]}return b}D={script:function(){be(V);var a=bu(arguments),b=D,c;if(bB){for(c=-1;++c<a.length;){if(B(a[c]))a[c]=a[c]();if(c===0){Y(function(){bt((typeof a[0]==q)?{src:a[0]}:a[0])})}else b=b.script(a[c]);b=b.wait()}}else{for(c=-1;++c<a.length;){if(B(a[c]))a[c]=a[c]()}Y(function(){for(c=-1;++c<a.length;){bt((typeof a[c]==q)?{src:a[c]}:a[c])}})}V=A(function(){s=i},5);return b},wait:function(a){be(V);s=i;if(!B(a))a=G;var b=H(t||J,l),c=b.trigger,d=function(){try{a()}catch(err){}c()};delete b.trigger;var g=function(){if(J&&!bk)bn=d;else d()};if(t&&!J)K.push(g);else Y(g);return b}};if(t){D.trigger=function(){var a,b=-1;while(a=K[++b])a();K=[]}}else D.trigger=G;return D}function bv(a){var b,c={},d={"UseCachePreload":"cache","UseLocalXHR":"xhr","UsePreloading":E,"AlwaysPreserveOrder":O,"AllowDuplicates":"dupe"},g={"AppendTo":z,"BasePath":"base"};for(b in d)g[b]=d[b];c.order=!(!v.order);for(b in g){if(g[P](b)&&v[g[b]]!=e)c[g[b]]=(a[b]!=e)?a[b]:v[g[b]]}for(b in d){if(d[P](b))c[d[b]]=!(!c[d[b]])}if(!c[E])c.cache=c.order=c.xhr=i;c.which=(c.which===w||c.which===L)?c.which:w;return c}p.$LAB={setGlobalDefaults:function(a){v=bv(a)},setOptions:function(a){return H(i,bv(a))},script:function(){return H().script.apply(e,arguments)},wait:function(){return H().wait.apply(e,arguments)}};(function(a,b,c){if(k[u]==e&&k[a]){k[u]="loading";k[a](b,c=function(){k.removeEventListener(b,c,i);k[u]=Z},i)}})("addEventListener","DOMContentLoaded")})(window);
|
||||
@@ -1,55 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html style="height: 100%">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>OpenERP</title>
|
||||
<link rel="shortcut icon" href="/base/static/src/img/favicon.ico" type="image/x-icon"/>
|
||||
|
||||
<script type="text/javascript" src="/base/static/lib/LABjs/LAB.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/underscore/underscore.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/underscore/underscore.string.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/qweb/qweb2.js"></script>
|
||||
<!-- Uncomment in order to use legacy QWeb
|
||||
<script type="text/javascript" src="/base/static/lib/qweb/qweb.js"></script>
|
||||
-->
|
||||
<script type="text/javascript" src="/base/static/lib/jquery/jquery-1.6.2.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/jquery.ui/js/jquery-ui-1.8.9.custom.min.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/jquery.ui/js/jquery-ui-timepicker-addon.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/jquery.ui.notify/js/jquery.notify.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/jquery.superfish/js/hoverIntent.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/jquery.superfish/js/superfish.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/jquery.contextmenu/jquery.contextmenu.r2.packed.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/datejs/date-en-US.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/json/json2.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/base.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/dates.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/chrome.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/data.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/views.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/form.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/list.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/list-editable.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/tree.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/search.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="/base/static/lib/jquery.ui/css/smoothness/jquery-ui-1.8.9.custom.css" />
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="/base/static/lib/jquery.ui.notify/css/ui.notify.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/base/static/lib/jquery.superfish/css/superfish.css" media="screen">
|
||||
|
||||
<link rel="stylesheet" href="/base/static/src/css/base.css" type="text/css"/>
|
||||
<!--[if lte IE 7]>
|
||||
<link rel="stylesheet" href="/base/static/src/css/base-ie7.css" type="text/css"/>
|
||||
<![endif]-->
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
QWeb = window.QWeb || new QWeb2.Engine();
|
||||
var oe = openerp.init();
|
||||
oe.base.webclient("oe");
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body id="oe" class="openerp">
|
||||
</body>
|
||||
</html>
|
||||
@@ -578,6 +578,10 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,
|
||||
display: none;
|
||||
}
|
||||
|
||||
.openerp .searchview_extended_delete_prop {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.openerp .searchview_extended_delete_group span,
|
||||
.openerp .searchview_extended_delete_prop span {
|
||||
font-size: 0.9em;
|
||||
@@ -592,6 +596,10 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
.openerp .oe-listview thead table {
|
||||
width: 100%;
|
||||
border: none;
|
||||
}
|
||||
.openerp .oe-listview tr.odd {
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
@@ -601,6 +609,10 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,
|
||||
.openerp .oe-listview tbody tr:hover {
|
||||
background-color: #eae9f0;
|
||||
}
|
||||
.openerp .oe-listview thead table tr,
|
||||
.openerp .oe-listview thead table tr:hover {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.openerp .oe-listview td,
|
||||
.openerp .oe-listview th {
|
||||
@@ -640,9 +652,11 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,
|
||||
|
||||
.openerp .oe-listview th.oe-actions {
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.openerp .oe-listview th.oe-list-pager {
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.openerp .oe-list-pager .oe-pager-state {
|
||||
cursor: pointer;
|
||||
@@ -672,29 +686,29 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%,
|
||||
rounded corners are a pain on tables: need to round not only table, but
|
||||
also on the first and last children of the first and last row
|
||||
*/
|
||||
.openerp .oe-listview table {
|
||||
.openerp .oe-listview table.oe-listview-content {
|
||||
-webkit-border-radius: 7px;
|
||||
-moz-border-radius: 7px;
|
||||
border-radius: 7px;
|
||||
}
|
||||
.openerp .oe-listview table thead tr:first-child th:first-child {
|
||||
.openerp .oe-listview table.oe-listview-content thead tr:first-child th:first-child {
|
||||
-webkit-border-top-left-radius: 7px;
|
||||
-moz-border-radius-topleft: 7px;
|
||||
border-top-left-radius: 7px;
|
||||
}
|
||||
.openerp .oe-listview table thead tr:first-child th:last-child {
|
||||
.openerp .oe-listview table.oe-listview-content thead tr:first-child th:last-child {
|
||||
-webkit-border-top-right-radius: 7px;
|
||||
-moz-border-radius-topright: 7px;
|
||||
border-top-right-radius: 7px;
|
||||
}
|
||||
.openerp .oe-listview table tfoot td:first-child,
|
||||
.openerp .oe-listview table tbody:last-child tr:last-child th:first-child {
|
||||
.openerp .oe-listview table.oe-listview-content tfoot td:first-child,
|
||||
.openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child th:first-child {
|
||||
-webkit-border-bottom-left-radius: 7px;
|
||||
-moz-border-radius-bottomleft: 7px;
|
||||
border-bottom-left-radius: 7px;
|
||||
}
|
||||
.openerp .oe-listview table tfoot td:last-child,
|
||||
.openerp .oe-listview table tbody:last-child tr:last-child td:last-child {
|
||||
.openerp .oe-listview table.oe-listview-content tfoot td:last-child,
|
||||
.openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child td:last-child {
|
||||
-webkit-border-bottom-right-radius: 7px;
|
||||
-moz-border-radius-bottomright: 7px;
|
||||
border-bottom-right-radius: 7px;
|
||||
|
||||
@@ -1,69 +1,3 @@
|
||||
/*---------------------------------------------------------
|
||||
* John Resig Class, to be moved to openerp.base.Class
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
(function() {
|
||||
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
|
||||
// The base Class implementation (does nothing)
|
||||
this.Class = function(){};
|
||||
|
||||
// Create a new Class that inherits from this class
|
||||
Class.extend = function(prop) {
|
||||
var _super = this.prototype;
|
||||
|
||||
// Instantiate a base class (but only create the instance,
|
||||
// don't run the init constructor)
|
||||
initializing = true;
|
||||
var prototype = new this();
|
||||
initializing = false;
|
||||
|
||||
// Copy the properties over onto the new prototype
|
||||
for (var name in prop) {
|
||||
// Check if we're overwriting an existing function
|
||||
prototype[name] = typeof prop[name] == "function" &&
|
||||
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
|
||||
(function(name, fn){
|
||||
return function() {
|
||||
var tmp = this._super;
|
||||
|
||||
// Add a new ._super() method that is the same method
|
||||
// but on the super-class
|
||||
this._super = _super[name];
|
||||
|
||||
// The method only need to be bound temporarily, so we
|
||||
// remove it when we're done executing
|
||||
var ret = fn.apply(this, arguments);
|
||||
this._super = tmp;
|
||||
|
||||
return ret;
|
||||
};
|
||||
})(name, prop[name]) :
|
||||
prop[name];
|
||||
}
|
||||
|
||||
// The dummy class constructor
|
||||
function Class() {
|
||||
// All construction is actually done in the init method
|
||||
if ( !initializing && this.init ) {
|
||||
var ret = this.init.apply(this, arguments);
|
||||
if (ret) { return ret; }
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Populate our constructed prototype object
|
||||
Class.prototype = prototype;
|
||||
|
||||
// Enforce the constructor to be what we expect
|
||||
Class.constructor = Class;
|
||||
|
||||
// And make this class extendable
|
||||
Class.extend = arguments.callee;
|
||||
|
||||
return Class;
|
||||
};
|
||||
})();
|
||||
|
||||
//---------------------------------------------------------
|
||||
// OpenERP initialisation and black magic about the pool
|
||||
//---------------------------------------------------------
|
||||
@@ -107,11 +41,13 @@
|
||||
_session_id: "session" + session_counter++,
|
||||
screen: openerp.screen,
|
||||
sessions: openerp.sessions,
|
||||
base: {}
|
||||
base: {},
|
||||
web_mobile: {}
|
||||
};
|
||||
openerp.sessions[new_instance._session_id] = new_instance;
|
||||
if (!skip_init)
|
||||
if (!skip_init){
|
||||
openerp.base(new_instance);
|
||||
}
|
||||
return new_instance;
|
||||
}
|
||||
};
|
||||
@@ -123,6 +59,7 @@
|
||||
|
||||
/** @namespace */
|
||||
openerp.base = function(instance) {
|
||||
openerp.base.controller(instance);
|
||||
openerp.base.dates(instance);
|
||||
openerp.base.chrome(instance);
|
||||
openerp.base.data(instance);
|
||||
@@ -135,9 +72,6 @@ openerp.base = function(instance) {
|
||||
if (openerp.base.list) {
|
||||
openerp.base.list(instance);
|
||||
}
|
||||
if (openerp.base.tree) {
|
||||
openerp.base.tree(instance);
|
||||
}
|
||||
if (openerp.base. m2o) {
|
||||
openerp.base.m2o(instance);
|
||||
}
|
||||
@@ -147,6 +81,12 @@ openerp.base = function(instance) {
|
||||
if (openerp.base.list && openerp.base.list.editable) {
|
||||
openerp.base.list.editable(instance);
|
||||
}
|
||||
if (openerp.web_mobile) {
|
||||
openerp.web_mobile(instance);
|
||||
}
|
||||
if (openerp.base.view_tree) {
|
||||
openerp.base.view_tree(instance);
|
||||
}
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
|
||||
+170
-420
@@ -4,61 +4,12 @@
|
||||
|
||||
openerp.base.chrome = function(openerp) {
|
||||
|
||||
openerp.base.callback = function(obj, method) {
|
||||
var callback = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var r;
|
||||
for(var i = 0; i < callback.callback_chain.length; i++) {
|
||||
var c = callback.callback_chain[i];
|
||||
if(c.unique) {
|
||||
callback.callback_chain.splice(i, 1);
|
||||
i -= 1;
|
||||
}
|
||||
r = c.callback.apply(c.self, c.args.concat(args));
|
||||
// TODO special value to stop the chain
|
||||
// openerp.base.callback_stop
|
||||
}
|
||||
return r;
|
||||
};
|
||||
callback.callback_chain = [];
|
||||
callback.add = function(f) {
|
||||
if(typeof(f) == 'function') {
|
||||
f = { callback: f, args: Array.prototype.slice.call(arguments, 1) };
|
||||
}
|
||||
f.self = f.self || null;
|
||||
f.args = f.args || [];
|
||||
f.unique = !!f.unique;
|
||||
if(f.position == 'last') {
|
||||
callback.callback_chain.push(f);
|
||||
} else {
|
||||
callback.callback_chain.unshift(f);
|
||||
}
|
||||
return callback;
|
||||
};
|
||||
callback.add_first = function(f) {
|
||||
return callback.add.apply(null,arguments);
|
||||
};
|
||||
callback.add_last = function(f) {
|
||||
return callback.add({
|
||||
callback: f,
|
||||
args: Array.prototype.slice.call(arguments, 1),
|
||||
position: "last"
|
||||
});
|
||||
};
|
||||
|
||||
return callback.add({
|
||||
callback: method,
|
||||
self:obj,
|
||||
args:Array.prototype.slice.call(arguments, 2)
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Base error for lookup failure
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
openerp.base.NotFound = Class.extend( /** @lends openerp.base.NotFound# */ {
|
||||
openerp.base.NotFound = openerp.base.Class.extend( /** @lends openerp.base.NotFound# */ {
|
||||
});
|
||||
openerp.base.KeyNotFound = openerp.base.NotFound.extend( /** @lends openerp.base.KeyNotFound# */ {
|
||||
/**
|
||||
@@ -91,7 +42,7 @@ openerp.base.ObjectNotFound = openerp.base.NotFound.extend( /** @lends openerp.b
|
||||
return "Could not find any object of path " + this.path;
|
||||
}
|
||||
});
|
||||
openerp.base.Registry = Class.extend( /** @lends openerp.base.Registry# */ {
|
||||
openerp.base.Registry = openerp.base.Class.extend( /** @lends openerp.base.Registry# */ {
|
||||
/**
|
||||
* Stores a mapping of arbitrary key (strings) to object paths (as strings
|
||||
* as well).
|
||||
@@ -185,144 +136,117 @@ openerp.base.Registry = Class.extend( /** @lends openerp.base.Registry# */ {
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.BasicController = Class.extend( /** @lends openerp.base.BasicController# */{
|
||||
/**
|
||||
* rpc operations, event binding and callback calling should be done in
|
||||
* start() instead of init so that event can be hooked in between.
|
||||
*
|
||||
* @constructs
|
||||
*/
|
||||
init: function(element_id) {
|
||||
this.element_id = element_id;
|
||||
this.$element = $('#' + element_id);
|
||||
if (element_id) {
|
||||
openerp.screen[element_id] = this;
|
||||
}
|
||||
|
||||
// Transform on_* method into openerp.base.callbacks
|
||||
for (var name in this) {
|
||||
if(typeof(this[name]) == "function") {
|
||||
this[name].debug_name = name;
|
||||
// bind ALL function to this not only on_and _do ?
|
||||
if((/^on_|^do_/).test(name)) {
|
||||
this[name] = openerp.base.callback(this, this[name]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* OpenERP session aware controller
|
||||
* a controller takes an already existing dom element and manage it
|
||||
*/
|
||||
openerp.base.Controller = openerp.base.Controller.extend( /** @lends openerp.base.Controller# */{
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
if(this.controller_parent && this.controller_parent.session) {
|
||||
this.session = this.controller_parent.session;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Controller start
|
||||
* event binding, rpc and callback calling required to initialize the
|
||||
* object can happen here
|
||||
* Performs a JSON-RPC call
|
||||
*
|
||||
* Returns a promise object letting callers (subclasses and direct callers)
|
||||
* know when this component is done starting
|
||||
*
|
||||
* @returns {jQuery.Deferred}
|
||||
* @param {String} url endpoint url
|
||||
* @param {Object} data RPC parameters
|
||||
* @param {Function} success RPC call success callback
|
||||
* @param {Function} error RPC call error callback
|
||||
* @returns {jQuery.Deferred} deferred object for the RPC call
|
||||
*/
|
||||
start: function() {
|
||||
// returns an already fulfilled promise. Maybe we could return nothing?
|
||||
// $.when can take non-deferred and in that case it simply considers
|
||||
// them all as fulfilled promises.
|
||||
// But in thise case we *have* to ensure callers use $.when and don't
|
||||
// try to call deferred methods on this return value.
|
||||
return $.Deferred().done().promise();
|
||||
rpc: function(url, data, success, error) {
|
||||
return this.session.rpc(url, data, success, error);
|
||||
},
|
||||
stop: function() {
|
||||
},
|
||||
log: function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var caller = arguments.callee.caller;
|
||||
// TODO add support for line number using
|
||||
// https://github.com/emwendelin/javascript-stacktrace/blob/master/stacktrace.js
|
||||
// args.unshift("" + caller.debug_name);
|
||||
this.on_log.apply(this,args);
|
||||
},
|
||||
on_log: function() {
|
||||
if(window.openerp.debug || (window.location.search.indexOf('?debug') !== -1)) {
|
||||
var notify = false;
|
||||
var body = false;
|
||||
if(window.console) {
|
||||
console.log(arguments);
|
||||
} else {
|
||||
body = true;
|
||||
}
|
||||
var a = Array.prototype.slice.call(arguments, 0);
|
||||
for(var i = 0; i < a.length; i++) {
|
||||
var v = a[i]==null ? "null" : a[i].toString();
|
||||
if(i==0) {
|
||||
notify = v.match(/^not/);
|
||||
body = v.match(/^bod/);
|
||||
}
|
||||
if(body) {
|
||||
$('<pre></pre>').text(v).appendTo($('body'));
|
||||
}
|
||||
if(notify && this.notification) {
|
||||
this.notification.notify("Logging:",v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_action: function(action, on_finished) {
|
||||
return this.parent.do_action(action, on_finished);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Generates an inherited class that replaces all the methods by null methods (methods
|
||||
* that does nothing and always return undefined).
|
||||
*
|
||||
* @param {Class} claz
|
||||
* @param {Object} add Additional functions to override.
|
||||
* @return {Class}
|
||||
* OpenERP session aware widget
|
||||
* A widget is a controller that doesnt take an element_id
|
||||
* it render its own html render() that you should insert into the dom
|
||||
* and bind it at start()
|
||||
*/
|
||||
openerp.base.generate_null_object_class = function(claz, add) {
|
||||
var newer = {};
|
||||
var copy_proto = function(prototype) {
|
||||
for (var name in prototype) {
|
||||
if(typeof prototype[name] == "function") {
|
||||
newer[name] = function() {};
|
||||
}
|
||||
openerp.base.BaseWidget = openerp.base.Controller.extend({
|
||||
/**
|
||||
* The name of the QWeb template that will be used for rendering. Must be
|
||||
* redefined in subclasses or the render() method can not be used.
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
template: null,
|
||||
/**
|
||||
* The prefix used to generate an id automatically. Should be redefined in
|
||||
* subclasses. If it is not defined, a default identifier will be used.
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
identifier_prefix: 'generic-identifier',
|
||||
/**
|
||||
* Base class for widgets. Handle rendering (based on a QWeb template),
|
||||
* identifier generation, parenting and destruction of the widget.
|
||||
* Also initialize the identifier.
|
||||
*
|
||||
* @constructs
|
||||
* @params {openerp.base.search.BaseWidget} parent The parent widget.
|
||||
*/
|
||||
init: function (parent) {
|
||||
this._super(parent);
|
||||
this.make_id(this.identifier_prefix);
|
||||
},
|
||||
/**
|
||||
* Sets and returns a globally unique identifier for the widget.
|
||||
*
|
||||
* If a prefix is appended, the identifier will be appended to it.
|
||||
*
|
||||
* @params sections prefix sections, empty/falsy sections will be removed
|
||||
*/
|
||||
make_id: function () {
|
||||
this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
|
||||
return this.element_id;
|
||||
},
|
||||
/**
|
||||
* Render the widget. This.template must be defined.
|
||||
* The content of the current object is passed as context to the template.
|
||||
*
|
||||
* @param {object} additional Additional context arguments to pass to the template.
|
||||
*/
|
||||
render: function (additional) {
|
||||
return QWeb.render(this.template, _.extend({}, this, additional != null ? additional : {}));
|
||||
},
|
||||
/**
|
||||
* "Starts" the widgets. Called at the end of the rendering, this allows
|
||||
* to get a jQuery object referring to the DOM ($element attribute).
|
||||
*/
|
||||
start: function () {
|
||||
this._super();
|
||||
var tmp = document.getElementById(this.element_id);
|
||||
this.$element = tmp ? $(tmp) : null;
|
||||
},
|
||||
/**
|
||||
* "Stops" the widgets. Called when the view destroys itself, this
|
||||
* lets the widgets clean up after themselves.
|
||||
*/
|
||||
stop: function () {
|
||||
if(this.$element != null) {
|
||||
this.$element.remove();
|
||||
}
|
||||
if (prototype.prototype)
|
||||
copy_proto(prototype.prototype);
|
||||
};
|
||||
copy_proto(claz.prototype);
|
||||
newer.init = openerp.base.BasicController.prototype.init;
|
||||
var tmpclass = claz.extend(newer);
|
||||
return tmpclass.extend(add || {});
|
||||
};
|
||||
|
||||
openerp.base.Notification = openerp.base.BasicController.extend({
|
||||
init: function(element_id) {
|
||||
this._super(element_id);
|
||||
this.$element.notify({
|
||||
speed: 500,
|
||||
expires: 1500
|
||||
});
|
||||
},
|
||||
notify: function(title, text) {
|
||||
this.$element.notify('create', {
|
||||
title: title,
|
||||
text: text
|
||||
});
|
||||
},
|
||||
warn: function(title, text) {
|
||||
this.$element.notify('create', 'oe_notification_alert', {
|
||||
title: title,
|
||||
text: text
|
||||
});
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.base.Session# */{
|
||||
openerp.base.Session = openerp.base.Controller.extend( /** @lends openerp.base.Session# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @extends openerp.base.BasicController
|
||||
* @param element_id to use for exception reporting
|
||||
* @param server
|
||||
* @param port
|
||||
*/
|
||||
init: function(element_id, server, port) {
|
||||
this._super(element_id);
|
||||
init: function(parent, element_id, server, port) {
|
||||
this._super(parent, element_id);
|
||||
this.server = (server == undefined) ? location.hostname : server;
|
||||
this.port = (port == undefined) ? location.port : port;
|
||||
this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp";
|
||||
@@ -337,12 +261,7 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
||||
this.context = {};
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
return this.session_restore().then(function () {
|
||||
self.on_session_valid();
|
||||
}, function () {
|
||||
self.on_session_invalid();
|
||||
});
|
||||
this.session_restore();
|
||||
},
|
||||
/**
|
||||
* Executes an RPC call, registering the provided callbacks.
|
||||
@@ -478,7 +397,7 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
||||
this.session_id = this.get_cookie('session_id');
|
||||
// we should do an rpc to confirm that this session_id is valid and if it is retrieve the information about db and login
|
||||
// then call on_session_valid
|
||||
return this.rpc('/base/session/check', {}, function () {}, function () {});
|
||||
this.on_session_valid();
|
||||
},
|
||||
/**
|
||||
* Saves the session id and uid locally
|
||||
@@ -506,7 +425,7 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
||||
for(var i=0; i<cookies.length; ++i) {
|
||||
var cookie = cookies[i].replace(/^\s*/, '');
|
||||
if(cookie.indexOf(nameEQ) === 0) {
|
||||
return decodeURIComponent(cookie.substring(nameEQ.length));
|
||||
return JSON.parse(decodeURIComponent(cookie.substring(nameEQ.length)));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -522,7 +441,7 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
||||
set_cookie: function (name, value, ttl) {
|
||||
ttl = ttl || 24*60*60*365;
|
||||
document.cookie = [
|
||||
this.element_id + '|' + name + '=' + encodeURIComponent(value),
|
||||
this.element_id + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)),
|
||||
'max-age=' + ttl,
|
||||
'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString()
|
||||
].join(';');
|
||||
@@ -533,14 +452,20 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
||||
load_modules: function() {
|
||||
var self = this;
|
||||
this.rpc('/base/session/modules', {}, function(result) {
|
||||
self.module_list = result['modules'];
|
||||
self.module_list = result;
|
||||
var modules = self.module_list.join(',');
|
||||
self.rpc('/base/session/csslist', {mods: modules}, self.do_load_css);
|
||||
self.rpc('/base/session/jslist', {"mods": modules}, self.debug ? self.do_load_modules_debug : self.do_load_modules_prod);
|
||||
if(self.debug || true) {
|
||||
self.rpc('/base/webclient/csslist', {"mods": modules}, self.do_load_css);
|
||||
self.rpc('/base/webclient/jslist', {"mods": modules}, self.do_load_js);
|
||||
} else {
|
||||
self.do_load_css(["/base/webclient/css?mods="+modules]);
|
||||
self.do_load_js(["/base/webclient/js?mods="+modules]);
|
||||
}
|
||||
openerp._modules_loaded = true;
|
||||
});
|
||||
},
|
||||
do_load_css: function (result) {
|
||||
_.each(result.files, function (file) {
|
||||
do_load_css: function (files) {
|
||||
_.each(files, function (file) {
|
||||
$('head').append($('<link>', {
|
||||
'href': file,
|
||||
'rel': 'stylesheet',
|
||||
@@ -548,16 +473,23 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
||||
}));
|
||||
});
|
||||
},
|
||||
do_load_modules_debug: function(result) {
|
||||
$LAB.setOptions({AlwaysPreserveOrder: true})
|
||||
.script(result.files)
|
||||
.wait(this.on_modules_loaded);
|
||||
},
|
||||
do_load_modules_prod: function() {
|
||||
// load merged ones
|
||||
// /base/session/css?mod=mod1,mod2,mod3
|
||||
// /base/session/js?mod=mod1,mod2,mod3
|
||||
// use $.getScript(‘your_3rd_party-script.js’); ? i want to keep lineno !
|
||||
do_load_js: function(files) {
|
||||
var self = this;
|
||||
if(files.length != 0) {
|
||||
var file = files.shift();
|
||||
var tag = document.createElement('script');
|
||||
tag.type = 'text/javascript';
|
||||
tag.src = file;
|
||||
tag.onload = tag.onreadystatechange = function() {
|
||||
if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done )
|
||||
return;
|
||||
tag.onload_done = true;
|
||||
self.do_load_js(files);
|
||||
};
|
||||
document.head.appendChild(tag);
|
||||
} else {
|
||||
this.on_modules_loaded();
|
||||
}
|
||||
},
|
||||
on_modules_loaded: function() {
|
||||
for(var j=0; j<this.module_list.length; j++) {
|
||||
@@ -571,213 +503,37 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
||||
this.module_loaded[mod] = true;
|
||||
}
|
||||
}
|
||||
openerp._modules_loaded = true;
|
||||
}
|
||||
});
|
||||
|
||||
// A controller takes an already existing element
|
||||
// new()
|
||||
// start()
|
||||
openerp.base.Controller = openerp.base.BasicController.extend( /** @lends openerp.base.Controller# */{
|
||||
/**
|
||||
* Controller manifest used to declare standard controller attributes
|
||||
*/
|
||||
controller_manifest: {
|
||||
register: null,
|
||||
template: "",
|
||||
element_post_prefix: false
|
||||
},
|
||||
/**
|
||||
* Controller registry,
|
||||
*/
|
||||
controller_registry: {
|
||||
},
|
||||
/**
|
||||
* Add a new child controller
|
||||
*/
|
||||
controller_get: function(key) {
|
||||
return this.controller_registry[key];
|
||||
// OR should build it ? setting parent correctly ?
|
||||
// function construct(constructor, args) {
|
||||
// function F() {
|
||||
// return constructor.apply(this, args);
|
||||
// }
|
||||
// F.prototype = constructor.prototype;
|
||||
// return new F();
|
||||
// }
|
||||
// var obj = this.controller_registry[key];
|
||||
// if(obj) {
|
||||
// return construct(obj, Array.prototype.slice.call(arguments, 1));
|
||||
// }
|
||||
},
|
||||
controller_new: function(key) {
|
||||
var self;
|
||||
// OR should contrustct it ? setting parent correctly ?
|
||||
function construct(constructor, args) {
|
||||
function F() {
|
||||
return constructor.apply(this, args);
|
||||
}
|
||||
F.prototype = constructor.prototype;
|
||||
return new F();
|
||||
}
|
||||
var obj = this.controller_registry[key];
|
||||
if(obj) {
|
||||
// TODO Prepend parent
|
||||
return construct(obj, Array.prototype.slice.call(arguments, 1));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @constructs
|
||||
* @extends openerp.base.BasicController
|
||||
*/
|
||||
init: function(parent_or_session, element_id) {
|
||||
this._super(element_id);
|
||||
this.controller_parent = null;
|
||||
this.controller_children = [];
|
||||
if(parent_or_session) {
|
||||
if(parent_or_session.session) {
|
||||
this.parent = parent_or_session;
|
||||
this.session = this.parent.session;
|
||||
if(this.parent.children) {
|
||||
this.parent.children.push(this);
|
||||
}
|
||||
} else {
|
||||
// TODO remove Backward compatilbility
|
||||
this.session = parent_or_session;
|
||||
}
|
||||
}
|
||||
// Apply manifest options
|
||||
if(this.controller_manifest) {
|
||||
var register = this.controller_manifest.register;
|
||||
// TODO accept a simple string
|
||||
if(register) {
|
||||
for(var i=0; i<register.length; i++) {
|
||||
this.controller_registry[register[i]] = this;
|
||||
}
|
||||
}
|
||||
// TODO if post prefix
|
||||
//this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Performs a JSON-RPC call
|
||||
*
|
||||
* @param {String} url endpoint url
|
||||
* @param {Object} data RPC parameters
|
||||
* @param {Function} success RPC call success callback
|
||||
* @param {Function} error RPC call error callback
|
||||
* @returns {jQuery.Deferred} deferred object for the RPC call
|
||||
*/
|
||||
rpc: function(url, data, success, error) {
|
||||
// TODO: support additional arguments ?
|
||||
return this.session.rpc(url, data, success, error);
|
||||
}
|
||||
});
|
||||
|
||||
// A widget is a controller that doesnt take an element_id
|
||||
// it render its own html that you should insert into the dom
|
||||
// and bind it a start()
|
||||
//
|
||||
// new()
|
||||
// render() and insert it place it where you want
|
||||
// start()
|
||||
openerp.base.BaseWidget = openerp.base.Controller.extend({
|
||||
/**
|
||||
* The name of the QWeb template that will be used for rendering. Must be
|
||||
* redefined in subclasses or the render() method can not be used.
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
template: null,
|
||||
/**
|
||||
* The prefix used to generate an id automatically. Should be redefined in
|
||||
* subclasses. If it is not defined, a default identifier will be used.
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
identifier_prefix: 'generic-identifier',
|
||||
/**
|
||||
* Base class for widgets. Handle rendering (based on a QWeb template),
|
||||
* identifier generation, parenting and destruction of the widget.
|
||||
* Also initialize the identifier.
|
||||
*
|
||||
* @constructs
|
||||
* @params {openerp.base.search.BaseWidget} parent The parent widget.
|
||||
*/
|
||||
init: function (parent, session) {
|
||||
this._super(session);
|
||||
this.children = [];
|
||||
this.parent = null;
|
||||
this.set_parent(parent);
|
||||
this.make_id(this.identifier_prefix);
|
||||
},
|
||||
/**
|
||||
* Sets and returns a globally unique identifier for the widget.
|
||||
*
|
||||
* If a prefix is appended, the identifier will be appended to it.
|
||||
*
|
||||
* @params sections prefix sections, empty/falsy sections will be removed
|
||||
*/
|
||||
make_id: function () {
|
||||
this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
|
||||
return this.element_id;
|
||||
},
|
||||
/**
|
||||
* "Starts" the widgets. Called at the end of the rendering, this allows
|
||||
* to get a jQuery object referring to the DOM ($element attribute).
|
||||
*/
|
||||
start: function () {
|
||||
this._super();
|
||||
var tmp = document.getElementById(this.element_id);
|
||||
this.$element = tmp ? $(tmp) : null;
|
||||
},
|
||||
/**
|
||||
* "Stops" the widgets. Called when the view destroys itself, this
|
||||
* lets the widgets clean up after themselves.
|
||||
*/
|
||||
stop: function () {
|
||||
var tmp_children = this.children;
|
||||
this.children = [];
|
||||
_.each(tmp_children, function(x) {
|
||||
x.stop();
|
||||
openerp.base.Notification = openerp.base.Controller.extend({
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.$element.notify({
|
||||
speed: 500,
|
||||
expires: 1500
|
||||
});
|
||||
if(this.$element != null) {
|
||||
this.$element.remove();
|
||||
}
|
||||
this.set_parent(null);
|
||||
this._super();
|
||||
},
|
||||
/**
|
||||
* Set the parent of this component, also un-register the previous parent
|
||||
* if there was one.
|
||||
*
|
||||
* @param {openerp.base.BaseWidget} parent The new parent.
|
||||
*/
|
||||
set_parent: function(parent) {
|
||||
if(this.parent) {
|
||||
this.parent.children = _.without(this.parent.children, this);
|
||||
}
|
||||
this.parent = parent;
|
||||
if(this.parent) {
|
||||
parent.children.push(this);
|
||||
}
|
||||
notify: function(title, text) {
|
||||
this.$element.notify('create', {
|
||||
title: title,
|
||||
text: text
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Render the widget. This.template must be defined.
|
||||
* The content of the current object is passed as context to the template.
|
||||
*
|
||||
* @param {object} additional Additional context arguments to pass to the template.
|
||||
*/
|
||||
render: function (additional) {
|
||||
return QWeb.render(this.template, _.extend({}, this, additional != null ? additional : {}));
|
||||
warn: function(title, text) {
|
||||
this.$element.notify('create', 'oe_notification_alert', {
|
||||
title: title,
|
||||
text: text
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.Dialog = openerp.base.BaseWidget.extend({
|
||||
dialog_title: "",
|
||||
identifier_prefix: 'dialog',
|
||||
init: function (session, options) {
|
||||
this._super(null, session);
|
||||
init: function (parent, options) {
|
||||
var self = this;
|
||||
this._super(parent);
|
||||
this.options = {
|
||||
modal: true,
|
||||
width: 'auto',
|
||||
@@ -787,7 +543,10 @@ openerp.base.Dialog = openerp.base.BaseWidget.extend({
|
||||
min_height: 0,
|
||||
max_height: '100%',
|
||||
autoOpen: false,
|
||||
buttons: {}
|
||||
buttons: {},
|
||||
close: function () {
|
||||
self.stop();
|
||||
}
|
||||
};
|
||||
for (var f in this) {
|
||||
if (f.substr(0, 10) == 'on_button_') {
|
||||
@@ -850,19 +609,15 @@ openerp.base.Dialog = openerp.base.BaseWidget.extend({
|
||||
this.set_options(options);
|
||||
this.$dialog.dialog(this.options).dialog('open');
|
||||
},
|
||||
close: function(options) {
|
||||
this.$dialog.dialog('close');
|
||||
},
|
||||
stop: function () {
|
||||
this.close();
|
||||
this.$dialog.dialog('destroy');
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.CrashManager = openerp.base.Dialog.extend({
|
||||
identifier_prefix: 'dialog_crash',
|
||||
init: function(session) {
|
||||
this._super(session);
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
this.session.on_rpc_error.add(this.on_rpc_error);
|
||||
},
|
||||
on_button_Ok: function() {
|
||||
@@ -896,11 +651,8 @@ openerp.base.CrashManager = openerp.base.Dialog.extend({
|
||||
});
|
||||
|
||||
openerp.base.Loading = openerp.base.Controller.extend({
|
||||
controller_manifest: {
|
||||
register: ["Loading"]
|
||||
},
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.count = 0;
|
||||
this.session.on_rpc_request.add_first(this.on_rpc_event, 1);
|
||||
this.session.on_rpc_response.add_last(this.on_rpc_event, -1);
|
||||
@@ -922,8 +674,8 @@ openerp.base.Database = openerp.base.Controller.extend({
|
||||
|
||||
openerp.base.Login = openerp.base.Controller.extend({
|
||||
remember_creditentials: true,
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.has_local_storage = typeof(localStorage) != 'undefined';
|
||||
this.selected_db = null;
|
||||
this.selected_login = null;
|
||||
@@ -999,8 +751,8 @@ openerp.base.Login = openerp.base.Controller.extend({
|
||||
});
|
||||
|
||||
openerp.base.Header = openerp.base.Controller.extend({
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
},
|
||||
start: function() {
|
||||
this.do_update();
|
||||
@@ -1013,8 +765,8 @@ openerp.base.Header = openerp.base.Controller.extend({
|
||||
});
|
||||
|
||||
openerp.base.Menu = openerp.base.Controller.extend({
|
||||
init: function(session, element_id, secondary_menu_id) {
|
||||
this._super(session, element_id);
|
||||
init: function(parent, element_id, secondary_menu_id) {
|
||||
this._super(parent, element_id);
|
||||
this.secondary_menu_id = secondary_menu_id;
|
||||
this.$secondary_menu = $("#" + secondary_menu_id).hide();
|
||||
this.menu = false;
|
||||
@@ -1105,33 +857,31 @@ openerp.base.ImportExport = openerp.base.Controller.extend({
|
||||
openerp.base.WebClient = openerp.base.Controller.extend({
|
||||
init: function(element_id) {
|
||||
this._super(null, element_id);
|
||||
this.view_manager = {};
|
||||
|
||||
QWeb.add_template("xml/base.xml");
|
||||
QWeb.add_template("/base/static/src/xml/base.xml");
|
||||
var params = {};
|
||||
if(jQuery.param != undefined &&
|
||||
jQuery.deparam(jQuery.param.querystring()).kitten != undefined) {
|
||||
if(jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) {
|
||||
this.$element.addClass("kitten-mode-activated");
|
||||
}
|
||||
this.$element.html(QWeb.render("Interface", params));
|
||||
|
||||
this.session = new openerp.base.Session("oe_errors");
|
||||
this.loading = new openerp.base.Loading(this.session, "oe_loading");
|
||||
this.crashmanager = new openerp.base.CrashManager(this.session);
|
||||
this.session = new openerp.base.Session(this,"oe_errors");
|
||||
this.loading = new openerp.base.Loading(this,"oe_loading");
|
||||
this.crashmanager = new openerp.base.CrashManager(this);
|
||||
this.crashmanager.start(false);
|
||||
|
||||
// Do you autorize this ?
|
||||
openerp.base.Controller.prototype.notification = new openerp.base.Notification("oe_notification");
|
||||
// Do you autorize this ? will be replaced by notify() in controller
|
||||
openerp.base.Controller.prototype.notification = new openerp.base.Notification(this, "oe_notification");
|
||||
|
||||
this.header = new openerp.base.Header(this.session, "oe_header");
|
||||
this.login = new openerp.base.Login(this.session, "oe_login");
|
||||
this.header = new openerp.base.Header(this, "oe_header");
|
||||
this.login = new openerp.base.Login(this, "oe_login");
|
||||
this.header.on_logout.add(this.login.on_logout);
|
||||
|
||||
this.session.on_session_invalid.add(this.login.do_ask_login);
|
||||
this.session.on_session_valid.add_last(this.header.do_update);
|
||||
this.session.on_session_valid.add_last(this.on_logged);
|
||||
|
||||
this.menu = new openerp.base.Menu(this.session, "oe_menu", "oe_secondary_menu");
|
||||
this.menu = new openerp.base.Menu(this, "oe_menu", "oe_secondary_menu");
|
||||
this.menu.on_action.add(this.on_menu_action);
|
||||
},
|
||||
start: function() {
|
||||
@@ -1142,9 +892,9 @@ openerp.base.WebClient = openerp.base.Controller.extend({
|
||||
this.notification.notify("OpenERP Client", "The openerp client has been initialized.");
|
||||
},
|
||||
on_logged: function() {
|
||||
this.action_manager = new openerp.base.ActionManager(this.session, "oe_app");
|
||||
this.action_manager = new openerp.base.ActionManager(this, "oe_app");
|
||||
this.action_manager.start();
|
||||
|
||||
|
||||
// if using saved actions, load the action and give it to action manager
|
||||
var parameters = jQuery.deparam(jQuery.param.querystring());
|
||||
if (parameters["s_action"] != undefined) {
|
||||
@@ -1170,7 +920,7 @@ openerp.base.WebClient = openerp.base.Controller.extend({
|
||||
load_url_state: function () {
|
||||
var self = this;
|
||||
// TODO: add actual loading if there is url state to unpack, test on window.location.hash
|
||||
var ds = new openerp.base.DataSetSearch(this.session, 'res.users');
|
||||
var ds = new openerp.base.DataSetSearch(this, 'res.users');
|
||||
ds.read_ids([parseInt(this.session.uid, 10)], ['action_id'], function (users) {
|
||||
var home_action = users[0].action_id;
|
||||
if (!home_action) {
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
/*---------------------------------------------------------
|
||||
* OpenERP controller framework
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
openerp.base.controller = function(instance) {
|
||||
/**
|
||||
* John Resig Class with factory improvement
|
||||
*/
|
||||
(function() {
|
||||
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
|
||||
// The base Class implementation (does nothing)
|
||||
this.Class = function(){};
|
||||
|
||||
// Create a new Class that inherits from this class
|
||||
Class.extend = function(prop) {
|
||||
var _super = this.prototype;
|
||||
|
||||
// Instantiate a base class (but only create the instance,
|
||||
// don't run the init constructor)
|
||||
initializing = true;
|
||||
var prototype = new this();
|
||||
initializing = false;
|
||||
|
||||
// Copy the properties over onto the new prototype
|
||||
for (var name in prop) {
|
||||
// Check if we're overwriting an existing function
|
||||
prototype[name] = typeof prop[name] == "function" &&
|
||||
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
|
||||
(function(name, fn){
|
||||
return function() {
|
||||
var tmp = this._super;
|
||||
|
||||
// Add a new ._super() method that is the same method
|
||||
// but on the super-class
|
||||
this._super = _super[name];
|
||||
|
||||
// The method only need to be bound temporarily, so we
|
||||
// remove it when we're done executing
|
||||
var ret = fn.apply(this, arguments);
|
||||
this._super = tmp;
|
||||
|
||||
return ret;
|
||||
};
|
||||
})(name, prop[name]) :
|
||||
prop[name];
|
||||
}
|
||||
|
||||
// The dummy class constructor
|
||||
function Class() {
|
||||
// All construction is actually done in the init method
|
||||
if ( !initializing && this.init ) {
|
||||
var ret = this.init.apply(this, arguments);
|
||||
if (ret) { return ret; }
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Populate our constructed prototype object
|
||||
Class.prototype = prototype;
|
||||
|
||||
// Enforce the constructor to be what we expect
|
||||
Class.constructor = Class;
|
||||
|
||||
// And make this class extendable
|
||||
Class.extend = arguments.callee;
|
||||
|
||||
return Class;
|
||||
};
|
||||
})();
|
||||
|
||||
// todo change john resig class to keep window clean
|
||||
instance.base.Class = window.Class
|
||||
|
||||
instance.base.callback = function(obj, method) {
|
||||
var callback = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var r;
|
||||
for(var i = 0; i < callback.callback_chain.length; i++) {
|
||||
var c = callback.callback_chain[i];
|
||||
if(c.unique) {
|
||||
callback.callback_chain.splice(i, 1);
|
||||
i -= 1;
|
||||
}
|
||||
r = c.callback.apply(c.self, c.args.concat(args));
|
||||
// TODO special value to stop the chain
|
||||
// openerp.base.callback_stop
|
||||
}
|
||||
return r;
|
||||
};
|
||||
callback.callback_chain = [];
|
||||
callback.add = function(f) {
|
||||
if(typeof(f) == 'function') {
|
||||
f = { callback: f, args: Array.prototype.slice.call(arguments, 1) };
|
||||
}
|
||||
f.self = f.self || null;
|
||||
f.args = f.args || [];
|
||||
f.unique = !!f.unique;
|
||||
if(f.position == 'last') {
|
||||
callback.callback_chain.push(f);
|
||||
} else {
|
||||
callback.callback_chain.unshift(f);
|
||||
}
|
||||
return callback;
|
||||
};
|
||||
callback.add_first = function(f) {
|
||||
return callback.add.apply(null,arguments);
|
||||
};
|
||||
callback.add_last = function(f) {
|
||||
return callback.add({
|
||||
callback: f,
|
||||
args: Array.prototype.slice.call(arguments, 1),
|
||||
position: "last"
|
||||
});
|
||||
};
|
||||
|
||||
return callback.add({
|
||||
callback: method,
|
||||
self:obj,
|
||||
args:Array.prototype.slice.call(arguments, 2)
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates an inherited class that replaces all the methods by null methods (methods
|
||||
* that does nothing and always return undefined).
|
||||
*
|
||||
* @param {Class} claz
|
||||
* @param {dict} add Additional functions to override.
|
||||
* @return {Class}
|
||||
*/
|
||||
instance.base.generate_null_object_class = function(claz, add) {
|
||||
var newer = {};
|
||||
var copy_proto = function(prototype) {
|
||||
for (var name in prototype) {
|
||||
if(typeof prototype[name] == "function") {
|
||||
newer[name] = function() {};
|
||||
}
|
||||
}
|
||||
if (prototype.prototype)
|
||||
copy_proto(prototype.prototype);
|
||||
};
|
||||
copy_proto(claz.prototype);
|
||||
newer.init = instance.base.Controller.prototype.init;
|
||||
var tmpclass = claz.extend(newer);
|
||||
return tmpclass.extend(add || {});
|
||||
};
|
||||
|
||||
/**
|
||||
* OpenERP Controller
|
||||
* TODO merge BaseWidget with Controller
|
||||
*/
|
||||
instance.base.Controller = instance.base.Class.extend( /** @lends instance.base.Controller# */{
|
||||
/**
|
||||
* @constructs
|
||||
* rpc operations, event binding and callback calling should be done in
|
||||
* start() instead of init so that events can be hooked in between.
|
||||
*/
|
||||
init: function(parent, element_id) {
|
||||
this.element_id = element_id;
|
||||
this.$element = $('#' + element_id);
|
||||
if (element_id) {
|
||||
instance.screen[element_id] = this;
|
||||
}
|
||||
// save the parent children relationship
|
||||
this.controller_parent = parent;
|
||||
this.controller_children = [];
|
||||
if(parent && parent.controller_children) {
|
||||
parent.controller_children.push(this);
|
||||
}
|
||||
// backward compatibility
|
||||
this.parent = this.controller_parent;
|
||||
this.children = this.controller_children;
|
||||
|
||||
// Transform on_* method into openerp.base.callbacks
|
||||
for (var name in this) {
|
||||
if(typeof(this[name]) == "function") {
|
||||
this[name].debug_name = name;
|
||||
// bind ALL function to this not only on_and _do ?
|
||||
if((/^on_|^do_/).test(name)) {
|
||||
this[name] = instance.base.callback(this, this[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Event binding, rpc and callback calling required to initialize the
|
||||
* object should happen here
|
||||
*
|
||||
* Returns a promise object letting callers (subclasses and direct callers)
|
||||
* know when this component is done starting
|
||||
*
|
||||
* @returns {jQuery.Deferred}
|
||||
*/
|
||||
start: function() {
|
||||
// returns an already fulfilled promise. Maybe we could return nothing?
|
||||
// $.when can take non-deferred and in that case it simply considers
|
||||
// them all as fulfilled promises.
|
||||
// But in thise case we *have* to ensure callers use $.when and don't
|
||||
// try to call deferred methods on this return value.
|
||||
return $.Deferred().done().promise();
|
||||
},
|
||||
stop: function() {
|
||||
if (this.parent && this.parent.children) {
|
||||
this.parent.children = _.without(this.parent.children, this);
|
||||
this.parent.controller_children = this.parent.children;
|
||||
}
|
||||
this.parent = null;
|
||||
this.controller_parent = null;
|
||||
},
|
||||
log: function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var caller = arguments.callee.caller;
|
||||
// TODO add support for line number using
|
||||
// https://github.com/emwendelin/javascript-stacktrace/blob/master/stacktrace.js
|
||||
// args.unshift("" + caller.debug_name);
|
||||
this.on_log.apply(this,args);
|
||||
},
|
||||
on_log: function() {
|
||||
if(window.openerp.debug || (window.location.search.indexOf('?debug') !== -1)) {
|
||||
var notify = false;
|
||||
var body = false;
|
||||
if(window.console) {
|
||||
console.log(arguments);
|
||||
} else {
|
||||
body = true;
|
||||
}
|
||||
var a = Array.prototype.slice.call(arguments, 0);
|
||||
for(var i = 0; i < a.length; i++) {
|
||||
var v = a[i]==null ? "null" : a[i].toString();
|
||||
if(i==0) {
|
||||
notify = v.match(/^not/);
|
||||
body = v.match(/^bod/);
|
||||
}
|
||||
if(body) {
|
||||
$('<pre></pre>').text(v).appendTo($('body'));
|
||||
}
|
||||
if(notify && this.notification) {
|
||||
this.notification.notify("Logging:",v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
@@ -39,18 +39,16 @@ openerp.base.DataGroup = openerp.base.Controller.extend( /** @lends openerp.bas
|
||||
* @param {Array} group_by sequence of fields by which to group
|
||||
* @param {Number} [level=0] nesting level of the group
|
||||
*/
|
||||
init: function(session, model, domain, context, group_by, level) {
|
||||
init: function(parent, model, domain, context, group_by, level) {
|
||||
this._super(parent, null);
|
||||
if (group_by) {
|
||||
if (group_by.length || context['group_by_no_leaf']) {
|
||||
return new openerp.base.ContainerDataGroup(
|
||||
session, model, domain, context, group_by, level);
|
||||
return new openerp.base.ContainerDataGroup( this, model, domain, context, group_by, level);
|
||||
} else {
|
||||
return new openerp.base.GrouplessDataGroup(
|
||||
session, model, domain, context, level);
|
||||
return new openerp.base.GrouplessDataGroup( this, model, domain, context, level);
|
||||
}
|
||||
}
|
||||
|
||||
this._super(session, null);
|
||||
this.model = model;
|
||||
this.context = context;
|
||||
this.domain = domain;
|
||||
@@ -59,8 +57,7 @@ openerp.base.DataGroup = openerp.base.Controller.extend( /** @lends openerp.bas
|
||||
},
|
||||
cls: 'DataGroup'
|
||||
});
|
||||
openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend(
|
||||
/** @lends openerp.base.ContainerDataGroup# */ {
|
||||
openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend( /** @lends openerp.base.ContainerDataGroup# */ {
|
||||
/**
|
||||
*
|
||||
* @constructs
|
||||
@@ -73,8 +70,8 @@ openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend(
|
||||
* @param group_by
|
||||
* @param level
|
||||
*/
|
||||
init: function (session, model, domain, context, group_by, level) {
|
||||
this._super(session, model, domain, context, null, level);
|
||||
init: function (parent, model, domain, context, group_by, level) {
|
||||
this._super(parent, model, domain, context, null, level);
|
||||
|
||||
this.group_by = group_by;
|
||||
},
|
||||
@@ -189,7 +186,7 @@ openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend(
|
||||
var child_context = _.extend({}, self.context, group.__context);
|
||||
return _.extend(
|
||||
new openerp.base.DataGroup(
|
||||
self.session, self.model, group.__domain,
|
||||
self, self.model, group.__domain,
|
||||
child_context, child_context.group_by,
|
||||
self.level + 1),
|
||||
group, {sort: self.sort});
|
||||
@@ -197,8 +194,7 @@ openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend(
|
||||
});
|
||||
}
|
||||
});
|
||||
openerp.base.GrouplessDataGroup = openerp.base.DataGroup.extend(
|
||||
/** @lends openerp.base.GrouplessDataGroup# */ {
|
||||
openerp.base.GrouplessDataGroup = openerp.base.DataGroup.extend( /** @lends openerp.base.GrouplessDataGroup# */ {
|
||||
/**
|
||||
*
|
||||
* @constructs
|
||||
@@ -210,18 +206,16 @@ openerp.base.GrouplessDataGroup = openerp.base.DataGroup.extend(
|
||||
* @param context
|
||||
* @param level
|
||||
*/
|
||||
init: function (session, model, domain, context, level) {
|
||||
this._super(session, model, domain, context, null, level);
|
||||
init: function (parent, model, domain, context, level) {
|
||||
this._super(parent, model, domain, context, null, level);
|
||||
},
|
||||
list: function (fields, ifGroups, ifRecords) {
|
||||
ifRecords(_.extend(
|
||||
new openerp.base.DataSetSearch(this.session, this.model),
|
||||
new openerp.base.DataSetSearch(this, this.model),
|
||||
{domain: this.domain, context: this.context, _sort: this.sort}));
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.StaticDataGroup = openerp.base.GrouplessDataGroup.extend(
|
||||
/** @lends openerp.base.StaticDataGroup# */ {
|
||||
openerp.base.StaticDataGroup = openerp.base.GrouplessDataGroup.extend( /** @lends openerp.base.StaticDataGroup# */ {
|
||||
/**
|
||||
* A specialization of groupless data groups, relying on a single static
|
||||
* dataset as its records provider.
|
||||
@@ -246,11 +240,12 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
||||
* @constructs
|
||||
* @extends openerp.base.Controller
|
||||
*
|
||||
* @param {openerp.base.Session} session current OpenERP session
|
||||
* @param {String} model the OpenERP model this dataset will manage
|
||||
*/
|
||||
init: function(session, model, context) {
|
||||
this._super(session);
|
||||
init: function(source_controller, model, context) {
|
||||
// we don't want the dataset to be a child of anything!
|
||||
this._super(null);
|
||||
this.session = source_controller ? source_controller.session : undefined;
|
||||
this.model = model;
|
||||
this.context = context || {};
|
||||
this.index = null;
|
||||
@@ -382,15 +377,11 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
|
||||
return this.context;
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.DataSetStatic = openerp.base.DataSet.extend({
|
||||
init: function(session, model, context, ids) {
|
||||
this._super(session, model, context);
|
||||
init: function(parent, model, context, ids) {
|
||||
this._super(parent, model, context);
|
||||
// all local records
|
||||
this.ids = ids || [];
|
||||
if (this.ids.length) {
|
||||
this.index = 0;
|
||||
}
|
||||
},
|
||||
read_slice: function (fields, offset, limit, callback) {
|
||||
var self = this;
|
||||
@@ -400,8 +391,10 @@ openerp.base.DataSetStatic = openerp.base.DataSet.extend({
|
||||
},
|
||||
set_ids: function (ids) {
|
||||
this.ids = ids;
|
||||
this.index = this.index <= this.ids.length - 1 ?
|
||||
this.index : (this.ids.length > 0 ? this.length - 1 : 0);
|
||||
if (this.index !== null) {
|
||||
this.index = this.index <= this.ids.length - 1 ?
|
||||
this.index : (this.ids.length > 0 ? this.length - 1 : 0);
|
||||
}
|
||||
},
|
||||
unlink: function(ids) {
|
||||
this.on_unlink(ids);
|
||||
@@ -411,18 +404,17 @@ openerp.base.DataSetStatic = openerp.base.DataSet.extend({
|
||||
this.set_ids(_.without.apply(null, [this.ids].concat(ids)));
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
||||
/**
|
||||
* @constructs
|
||||
*
|
||||
* @param {openerp.base.Session} session
|
||||
* @param {Object} parent
|
||||
* @param {String} model
|
||||
* @param {Object} context
|
||||
* @param {Array} domain
|
||||
*/
|
||||
init: function(session, model, context, domain) {
|
||||
this._super(session, model, context);
|
||||
init: function(parent, model, context, domain) {
|
||||
this._super(parent, model, context);
|
||||
this.domain = domain || [];
|
||||
this._sort = [];
|
||||
this.offset = 0;
|
||||
@@ -486,14 +478,15 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({
|
||||
var self = this;
|
||||
return this._super(ids, function(result) {
|
||||
self.ids = _.without.apply(_, [self.ids].concat(ids));
|
||||
self.index = self.index <= self.ids.length - 1 ?
|
||||
self.index : (self.ids.length > 0 ? self.ids.length -1 : 0);
|
||||
if (this.index !== null) {
|
||||
self.index = self.index <= self.ids.length - 1 ?
|
||||
self.index : (self.ids.length > 0 ? self.ids.length -1 : 0);
|
||||
}
|
||||
if (callback)
|
||||
callback(result);
|
||||
}, error_callback);
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.BufferedDataSet = openerp.base.DataSetStatic.extend({
|
||||
virtual_id_prefix: "one2many_v_id_",
|
||||
virtual_id_regex: /one2many_v_id_.*/,
|
||||
@@ -598,7 +591,6 @@ openerp.base.BufferedDataSet = openerp.base.DataSetStatic.extend({
|
||||
return completion.promise();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.ReadOnlyDataSetSearch = openerp.base.DataSetSearch.extend({
|
||||
create: function(data, callback, error_callback) {
|
||||
this.on_create(data);
|
||||
|
||||
@@ -17,9 +17,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
*
|
||||
* @property {openerp.base.Registry} registry=openerp.base.form.widgets widgets registry for this form view instance
|
||||
*/
|
||||
init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
this._super(session, element_id);
|
||||
this.view_manager = view_manager || new openerp.base.NullViewManager();
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
@@ -37,6 +37,8 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.registry = openerp.base.form.widgets;
|
||||
this.has_been_loaded = $.Deferred();
|
||||
this.$form_header = null;
|
||||
this.options = options || {};
|
||||
_.defaults(this.options, {"always_show_new_button": true});
|
||||
},
|
||||
start: function() {
|
||||
//this.log('Starting FormView '+this.model+this.view_id)
|
||||
@@ -79,19 +81,27 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.$form_header.find('button.oe_form_button_cancel').click(this.do_cancel);
|
||||
this.$form_header.find('button.oe_form_button_new').click(this.on_button_new);
|
||||
|
||||
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar);
|
||||
this.$form_header.find('button.oe_get_xml_view').click(function() {
|
||||
$('<xmp>' + openerp.base.json_node_to_xml(self.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600});
|
||||
});
|
||||
|
||||
if(this.view_manager.sidebar)
|
||||
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar);
|
||||
this.has_been_loaded.resolve();
|
||||
},
|
||||
do_show: function () {
|
||||
var self = this;
|
||||
var promise;
|
||||
if (this.dataset.index === null) {
|
||||
// null index means we should start a new record
|
||||
this.on_button_new();
|
||||
promise = this.on_button_new();
|
||||
} else {
|
||||
this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded);
|
||||
promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded);
|
||||
}
|
||||
self.$element.show();
|
||||
this.view_manager.sidebar.do_refresh(true);
|
||||
if(this.view_manager.sidebar)
|
||||
this.view_manager.sidebar.do_refresh(true);
|
||||
return promise;
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
@@ -103,7 +113,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
if (!record.id) {
|
||||
this.$form_header.find('.oe_form_on_create').show();
|
||||
this.$form_header.find('.oe_form_on_update').hide();
|
||||
this.$form_header.find('button.oe_form_button_new').hide();
|
||||
if (!this.options["always_show_new_button"]) {
|
||||
this.$form_header.find('button.oe_form_button_new').hide();
|
||||
}
|
||||
} else {
|
||||
this.$form_header.find('.oe_form_on_create').hide();
|
||||
this.$form_header.find('.oe_form_on_update').show();
|
||||
@@ -231,10 +243,11 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
}
|
||||
},
|
||||
on_processed_onchange: function(response, processed) {
|
||||
var result = response.result;
|
||||
var result = response;
|
||||
if (result.value) {
|
||||
for (var f in result.value) {
|
||||
var field = this.fields[f];
|
||||
// If field is not defined in the view, just ignore it
|
||||
if (field) {
|
||||
var value = result.value[f];
|
||||
processed.push(field.name);
|
||||
@@ -245,8 +258,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.do_onchange(field, processed);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// this is a common case, the normal behavior should be to ignore it
|
||||
}
|
||||
}
|
||||
this.on_form_changed();
|
||||
@@ -262,16 +273,20 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
});
|
||||
}
|
||||
if (result.domain) {
|
||||
// Will be removed ?
|
||||
// TODO:
|
||||
}
|
||||
this.ready = true;
|
||||
},
|
||||
on_button_new: function() {
|
||||
var self = this;
|
||||
var def = $.Deferred();
|
||||
$.when(this.has_been_loaded).then(function() {
|
||||
self.dataset.default_get(
|
||||
_.keys(self.fields_view.fields), self.on_record_loaded);
|
||||
_.keys(self.fields_view.fields)).then(self.on_record_loaded).then(function() {
|
||||
def.resolve();
|
||||
});
|
||||
});
|
||||
return def.promise();
|
||||
},
|
||||
/**
|
||||
* Triggers saving the form's record. Chooses between creating a new
|
||||
@@ -392,20 +407,19 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.notification.notify("Cancelling form");
|
||||
},
|
||||
do_update_sidebar: function() {
|
||||
if (this.flags.sidebar === false) {
|
||||
if (this.flags.sidebar === false || this.view_manager.sidebar === undefined) {
|
||||
return;
|
||||
}
|
||||
if (!this.datarecord.id) {
|
||||
this.on_attachments_loaded([]);
|
||||
} else {
|
||||
// TODO fme: modify this so it doesn't try to load attachments when there is not sidebar
|
||||
/*(new openerp.base.DataSetSearch(
|
||||
this.session, 'ir.attachment', this.dataset.get_context(),
|
||||
(new openerp.base.DataSetSearch(
|
||||
this, 'ir.attachment', this.dataset.get_context(),
|
||||
[['res_model', '=', this.dataset.model],
|
||||
['res_id', '=', this.datarecord.id],
|
||||
['type', 'in', ['binary', 'url']]])).read_slice(
|
||||
['name', 'url', 'type'], false, false,
|
||||
this.on_attachments_loaded);*/
|
||||
this.on_attachments_loaded);
|
||||
}
|
||||
},
|
||||
on_attachments_loaded: function(attachments) {
|
||||
@@ -526,7 +540,7 @@ openerp.base.form.Widget = openerp.base.Controller.extend({
|
||||
this.element_name = this.element_name || this.type;
|
||||
this.element_id = [this.view.element_id, this.element_name, this.view.widgets_counter++].join("_");
|
||||
|
||||
this._super(this.view.session, this.element_id);
|
||||
this._super(view, this.element_id);
|
||||
|
||||
this.view.widgets[this.element_id] = this;
|
||||
this.children = node.children;
|
||||
@@ -825,8 +839,10 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({
|
||||
* the fields'context with the action's context.
|
||||
*/
|
||||
build_context: function() {
|
||||
var a_context = this.view.dataset.get_context() || {};
|
||||
var f_context = this.field.context || {};
|
||||
// I previously belevied contexts should be herrited, but now I doubt it
|
||||
//var a_context = this.view.dataset.get_context() || {};
|
||||
var f_context = this.field.context || null;
|
||||
// maybe the default_get should only be used when we do a default_get?
|
||||
var v_context1 = this.node.attrs.default_get || {};
|
||||
var v_context2 = this.node.attrs.context || {};
|
||||
var v_context = new openerp.base.CompoundContext(v_context1, v_context2);
|
||||
@@ -834,17 +850,19 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({
|
||||
var fields_values = this._build_view_fields_values();
|
||||
v_context.set_eval_context(fields_values);
|
||||
}
|
||||
var ctx = new openerp.base.CompoundContext(a_context, f_context, v_context);
|
||||
// if there is a context on the node, overrides the model's context
|
||||
var ctx = f_context || v_context;
|
||||
return ctx;
|
||||
},
|
||||
build_domain: function() {
|
||||
var f_domain = this.field.domain || [];
|
||||
var f_domain = this.field.domain || null;
|
||||
var v_domain = this.node.attrs.domain || [];
|
||||
if (!(v_domain instanceof Array) || true) { //TODO niv: remove || true
|
||||
var fields_values = this._build_view_fields_values();
|
||||
v_domain = new openerp.base.CompoundDomain(v_domain).set_eval_context(fields_values);
|
||||
}
|
||||
return new openerp.base.CompoundDomain(f_domain, v_domain);
|
||||
// if there is a domain on the node, overrides the model's domain
|
||||
return f_domain || v_domain;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1238,6 +1256,21 @@ openerp.base.form.FieldSelection = openerp.base.form.Field.extend({
|
||||
});
|
||||
})();
|
||||
|
||||
openerp.base.form.dialog = function(content, options) {
|
||||
options = _.extend({
|
||||
autoOpen: true,
|
||||
width: '90%',
|
||||
height: '90%',
|
||||
min_width: '800px',
|
||||
min_height: '600px'
|
||||
}, options || {});
|
||||
options.autoOpen = true;
|
||||
var dialog = new openerp.base.Dialog(null, options);
|
||||
dialog.$dialog = $(content).dialog(dialog.options);
|
||||
console.log(dialog.options)
|
||||
return dialog.$dialog;
|
||||
}
|
||||
|
||||
openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
@@ -1267,7 +1300,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
if (!self.value) {
|
||||
return;
|
||||
}
|
||||
var pop = new openerp.base.form.FormOpenPopup(null, self.view.session);
|
||||
var pop = new openerp.base.form.FormOpenPopup(self.view);
|
||||
pop.show_element(self.field.relation, self.value[0],self.build_context(), {});
|
||||
pop.on_write_completed.add_last(function() {
|
||||
self.set_value(self.value[0]);
|
||||
@@ -1355,13 +1388,13 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
var search_val = request.term;
|
||||
var self = this;
|
||||
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, self.build_context());
|
||||
var dataset = new openerp.base.DataSetStatic(this, this.field.relation, self.build_context());
|
||||
|
||||
dataset.name_search(search_val, self.build_domain(), 'ilike',
|
||||
this.limit + 1, function(data) {
|
||||
self.last_search = data.result;
|
||||
self.last_search = data;
|
||||
// possible selections for the m2o
|
||||
var values = _.map(data.result, function(x) {
|
||||
var values = _.map(data, function(x) {
|
||||
return {label: $('<span />').text(x[1]).html(), name:x[1], id:x[0]};
|
||||
});
|
||||
|
||||
@@ -1372,7 +1405,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
dataset.name_search(search_val, self.build_domain(), 'ilike'
|
||||
, false, function(data) {
|
||||
self._change_int_value(null);
|
||||
self._search_create_popup("search", data.result);
|
||||
self._search_create_popup("search", data);
|
||||
});
|
||||
}});
|
||||
}
|
||||
@@ -1397,9 +1430,9 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
},
|
||||
_quick_create: function(name) {
|
||||
var self = this;
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, self.build_context());
|
||||
var dataset = new openerp.base.DataSetStatic(this, this.field.relation, self.build_context());
|
||||
dataset.name_create(name, function(data) {
|
||||
self._change_int_ext_value(data.result);
|
||||
self._change_int_ext_value(data);
|
||||
}).fail(function(error, event) {
|
||||
event.preventDefault();
|
||||
self._change_int_value(null);
|
||||
@@ -1409,7 +1442,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
// all search/create popup handling
|
||||
_search_create_popup: function(view, ids, context) {
|
||||
var self = this;
|
||||
var pop = new openerp.base.form.SelectCreatePopup(null, self.view.session);
|
||||
var pop = new openerp.base.form.SelectCreatePopup(this);
|
||||
pop.select_element(self.field.relation,{
|
||||
initial_ids: ids ? _.map(ids, function(x) {return x[0]}) : undefined,
|
||||
initial_view: view,
|
||||
@@ -1417,9 +1450,9 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
}, self.build_domain(),
|
||||
new openerp.base.CompoundContext(self.build_context(), context || {}));
|
||||
pop.on_select_elements.add(function(element_ids) {
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, self.build_context());
|
||||
var dataset = new openerp.base.DataSetStatic(this, this.field.relation, self.build_context());
|
||||
dataset.name_get([element_ids[0]], function(data) {
|
||||
self._change_int_ext_value(data.result[0]);
|
||||
self._change_int_ext_value(data[0]);
|
||||
pop.stop();
|
||||
});
|
||||
});
|
||||
@@ -1455,9 +1488,9 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
|
||||
self._change_int_ext_value(rval);
|
||||
};
|
||||
if(typeof(value) === "number") {
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, self.build_context());
|
||||
var dataset = new openerp.base.DataSetStatic(this, this.field.relation, self.build_context());
|
||||
dataset.name_get([value], function(data) {
|
||||
real_set_value(data.result[0]);
|
||||
real_set_value(data[0]);
|
||||
}).fail(function() {self.tmp_value = undefined;});
|
||||
} else {
|
||||
setTimeout(function() {real_set_value(value);}, 0);
|
||||
@@ -1533,13 +1566,14 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
this._super(view, node);
|
||||
this.template = "FieldOne2Many";
|
||||
this.is_started = $.Deferred();
|
||||
this.form_last_update = $.Deferred();
|
||||
},
|
||||
start: function() {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
var self = this;
|
||||
|
||||
this.dataset = new openerp.base.form.One2ManyDataSet(this.session, this.field.relation);
|
||||
this.dataset = new openerp.base.form.One2ManyDataSet(this, this.field.relation);
|
||||
this.dataset.o2m = this;
|
||||
this.dataset.parent_view = this.view;
|
||||
this.dataset.on_change.add_last(function() {
|
||||
@@ -1563,17 +1597,21 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
});
|
||||
this.views = views;
|
||||
|
||||
this.viewmanager = new openerp.base.ViewManager(this.view.session,
|
||||
this.element_id, this.dataset, views);
|
||||
this.viewmanager = new openerp.base.ViewManager(this, this.element_id, this.dataset, views);
|
||||
this.viewmanager.registry = openerp.base.views.clone({
|
||||
list: 'openerp.base.form.One2ManyListView'
|
||||
list: 'openerp.base.form.One2ManyListView',
|
||||
form: 'openerp.base.form.One2ManyFormView'
|
||||
});
|
||||
var once = $.Deferred().then(function() {
|
||||
self.form_last_update.resolve();
|
||||
});
|
||||
|
||||
this.viewmanager.on_controller_inited.add_last(function(view_type, controller) {
|
||||
if (view_type == "list") {
|
||||
controller.o2m = self;
|
||||
} else if (view_type == "form") {
|
||||
// TODO niv
|
||||
controller.on_record_loaded.add_last(function() {
|
||||
once.resolve();
|
||||
});
|
||||
}
|
||||
self.is_started.resolve();
|
||||
});
|
||||
@@ -1587,7 +1625,12 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
|
||||
if(self.viewmanager.active_view === "list") {
|
||||
view.reload_content();
|
||||
} else if (self.viewmanager.active_view === "form") {
|
||||
// TODO niv: implement
|
||||
if (this.dataset.index === null && this.dataset.ids.length >= 1) {
|
||||
this.dataset.index = 0;
|
||||
}
|
||||
this.form_last_update.then(function() {
|
||||
this.form_last_update = view.do_show();
|
||||
});
|
||||
}
|
||||
},
|
||||
set_value_from_ui: function() {},
|
||||
@@ -1678,13 +1721,17 @@ openerp.base.form.One2ManyDataSet = openerp.base.BufferedDataSet.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.One2ManyFormView = openerp.base.FormView.extend({
|
||||
|
||||
});
|
||||
|
||||
openerp.base.form.One2ManyListView = openerp.base.ListView.extend({
|
||||
do_add_record: function () {
|
||||
if (this.options.editable) {
|
||||
this._super.apply(this, arguments);
|
||||
} else {
|
||||
var self = this;
|
||||
var pop = new openerp.base.form.SelectCreatePopup(null, self.o2m.view.session);
|
||||
var pop = new openerp.base.form.SelectCreatePopup(this);
|
||||
pop.select_element(self.o2m.field.relation,{
|
||||
initial_view: "form",
|
||||
alternative_form_view: self.o2m.field.views ? self.o2m.field.views["form"] : undefined,
|
||||
@@ -1703,7 +1750,7 @@ openerp.base.form.One2ManyListView = openerp.base.ListView.extend({
|
||||
},
|
||||
do_activate_record: function(index, id) {
|
||||
var self = this;
|
||||
var pop = new openerp.base.form.FormOpenPopup(null, self.o2m.view.session);
|
||||
var pop = new openerp.base.form.FormOpenPopup(self.o2m.view);
|
||||
pop.show_element(self.o2m.field.relation, id, self.o2m.build_context(),{
|
||||
auto_write: false,
|
||||
alternative_form_view: self.o2m.field.views ? self.o2m.field.views["form"] : undefined,
|
||||
@@ -1730,15 +1777,13 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
||||
|
||||
var self = this;
|
||||
|
||||
this.dataset = new openerp.base.form.Many2ManyDataSet(
|
||||
this.session, this.field.relation);
|
||||
this.dataset = new openerp.base.form.Many2ManyDataSet( this, this.field.relation);
|
||||
this.dataset.m2m = this;
|
||||
this.dataset.on_unlink.add_last(function(ids) {
|
||||
self.on_ui_change();
|
||||
});
|
||||
|
||||
this.list_view = new openerp.base.form.Many2ManyListView(
|
||||
null, this.view.session, this.list_id, this.dataset, false, {
|
||||
this.list_view = new openerp.base.form.Many2ManyListView(new openerp.base.NullViewManager(this), this.list_id, this.dataset, false, {
|
||||
'addable': 'Add',
|
||||
'selectable': self.multi_selection
|
||||
});
|
||||
@@ -1781,8 +1826,7 @@ openerp.base.form.Many2ManyDataSet = openerp.base.DataSetStatic.extend({
|
||||
|
||||
openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({
|
||||
do_add_record: function () {
|
||||
var pop = new openerp.base.form.SelectCreatePopup(
|
||||
null, this.m2m_field.view.session);
|
||||
var pop = new openerp.base.form.SelectCreatePopup(this);
|
||||
pop.select_element(this.model, {},
|
||||
new openerp.base.CompoundDomain(this.m2m_field.build_domain(), ["!", ["id", "in", this.m2m_field.dataset.ids]]),
|
||||
this.m2m_field.build_context());
|
||||
@@ -1800,7 +1844,7 @@ openerp.base.form.Many2ManyListView = openerp.base.ListView.extend({
|
||||
},
|
||||
do_activate_record: function(index, id) {
|
||||
var self = this;
|
||||
var pop = new openerp.base.form.FormOpenPopup(null, this.m2m_field.view.session);
|
||||
var pop = new openerp.base.form.FormOpenPopup(this);
|
||||
pop.show_element(this.dataset.model, id, this.m2m_field.build_context(), {});
|
||||
pop.on_write_completed.add_last(function() {
|
||||
self.reload_content();
|
||||
@@ -1826,15 +1870,12 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
||||
this.context = context || {};
|
||||
this.options = _.defaults(options || {}, {"initial_view": "search", "auto_create": true});
|
||||
this.initial_ids = this.options.initial_ids;
|
||||
jQuery(this.render()).dialog({title: '',
|
||||
modal: true,
|
||||
width: 960,
|
||||
height: 600});
|
||||
openerp.base.form.dialog(this.render());
|
||||
this.start();
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
this.dataset = new openerp.base.ReadOnlyDataSetSearch(this.session, this.model,
|
||||
this.dataset = new openerp.base.ReadOnlyDataSetSearch(this, this.model,
|
||||
this.context);
|
||||
this.dataset.parent_view = this.options.parent_view;
|
||||
if (this.options.initial_view == "search") {
|
||||
@@ -1848,7 +1889,7 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
||||
if (this.searchview) {
|
||||
this.searchview.stop();
|
||||
}
|
||||
this.searchview = new openerp.base.SearchView(null, this.session,
|
||||
this.searchview = new openerp.base.SearchView(this,
|
||||
this.element_id + "_search", this.dataset, false, {
|
||||
"selectable": !this.options.disable_multiple_selection,
|
||||
"deletable": false
|
||||
@@ -1876,7 +1917,7 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
||||
$sbutton.click(function() {
|
||||
self.on_select_elements(self.selected_ids);
|
||||
});
|
||||
self.view_list = new openerp.base.form.SelectCreateListView( null, self.session,
|
||||
self.view_list = new openerp.base.form.SelectCreateListView(self,
|
||||
self.element_id + "_view_list", self.dataset, false,
|
||||
{'deletable': false});
|
||||
self.view_list.popup = self;
|
||||
@@ -1891,7 +1932,7 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
||||
if (!this.options.auto_create)
|
||||
return;
|
||||
var self = this;
|
||||
var wdataset = new openerp.base.DataSetSearch(this.session, this.model, this.context, this.domain);
|
||||
var wdataset = new openerp.base.DataSetSearch(this, this.model, this.context, this.domain);
|
||||
wdataset.parent_view = this.options.parent_view;
|
||||
wdataset.create(data, function(r) {
|
||||
self.on_select_elements([r.result]);
|
||||
@@ -1916,8 +1957,7 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
|
||||
this.view_list.$element.hide();
|
||||
}
|
||||
this.dataset.index = null;
|
||||
this.view_form = new openerp.base.FormView(null, this.session,
|
||||
this.element_id + "_view_form", this.dataset, false);
|
||||
this.view_form = new openerp.base.FormView(this, this.element_id + "_view_form", this.dataset, false);
|
||||
if (this.options.alternative_form_view) {
|
||||
this.view_form.set_embedded_view(this.options.alternative_form_view);
|
||||
}
|
||||
@@ -1974,8 +2014,7 @@ openerp.base.form.FormOpenPopup = openerp.base.BaseWidget.extend({
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
this.dataset = new openerp.base.ReadOnlyDataSetSearch(this.session, this.model,
|
||||
this.context);
|
||||
this.dataset = new openerp.base.ReadOnlyDataSetSearch(this, this.model, this.context);
|
||||
this.dataset.ids = [this.row_id];
|
||||
this.dataset.index = 0;
|
||||
this.dataset.parent_view = this.options.parent_view;
|
||||
@@ -1986,7 +2025,7 @@ openerp.base.form.FormOpenPopup = openerp.base.BaseWidget.extend({
|
||||
if (!this.options.auto_write)
|
||||
return;
|
||||
var self = this;
|
||||
var wdataset = new openerp.base.DataSetSearch(this.session, this.model, this.context, this.domain);
|
||||
var wdataset = new openerp.base.DataSetSearch(this, this.model, this.context, this.domain);
|
||||
wdataset.parent_view = this.options.parent_view;
|
||||
wdataset.write(id, data, function(r) {
|
||||
self.on_write_completed();
|
||||
@@ -1995,8 +2034,7 @@ openerp.base.form.FormOpenPopup = openerp.base.BaseWidget.extend({
|
||||
on_write_completed: function() {},
|
||||
setup_form_view: function() {
|
||||
var self = this;
|
||||
this.view_form = new openerp.base.FormView(null, this.session,
|
||||
this.element_id + "_view_form", this.dataset, false);
|
||||
this.view_form = new openerp.base.FormView(this, this.element_id + "_view_form", this.dataset, false);
|
||||
if (this.options.alternative_form_view) {
|
||||
this.view_form.set_embedded_view(this.options.alternative_form_view);
|
||||
}
|
||||
@@ -2018,10 +2056,10 @@ openerp.base.form.FormOpenPopup = openerp.base.BaseWidget.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.FieldReference = openerp.base.form.Field.extend({
|
||||
openerp.base.form.FieldReference = openerp.base.form.FieldChar.extend({
|
||||
init: function(view, node) {
|
||||
this._super(view, node);
|
||||
this.template = "FieldReference";
|
||||
//this.template = "FieldReference";
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2039,6 +2077,10 @@ openerp.base.form.FieldBinary = openerp.base.form.Field.extend({
|
||||
},
|
||||
set_value_from_ui: function() {
|
||||
},
|
||||
update_dom: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$element.find('.oe-binary').toggle(!this.readonly);
|
||||
},
|
||||
human_filesize : function(size) {
|
||||
var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
var i = 0;
|
||||
@@ -2136,6 +2178,13 @@ openerp.base.form.FieldBinaryImage = openerp.base.form.FieldBinary.extend({
|
||||
this._super.apply(this, arguments);
|
||||
this.$image = this.$element.find('img.oe-binary-image');
|
||||
},
|
||||
set_value: function(value) {
|
||||
this._super.apply(this, arguments);
|
||||
this.set_image_maxwidth();
|
||||
var url = '/base/binary/image?session_id=' + this.session.session_id + '&model=' +
|
||||
this.view.dataset.model +'&id=' + (this.view.datarecord.id || '') + '&field=' + this.name + '&t=' + (new Date().getTime())
|
||||
this.$image.attr('src', url);
|
||||
},
|
||||
set_image_maxwidth: function() {
|
||||
this.$image.css('max-width', this.$element.width());
|
||||
},
|
||||
@@ -2151,13 +2200,6 @@ openerp.base.form.FieldBinaryImage = openerp.base.form.FieldBinary.extend({
|
||||
on_clear: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$image.attr('src', '/base/static/src/img/placeholder.png');
|
||||
},
|
||||
set_value: function(value) {
|
||||
this._super.apply(this, arguments);
|
||||
this.set_image_maxwidth();
|
||||
var url = '/base/binary/image?session_id=' + this.session.session_id + '&model=' +
|
||||
this.view.dataset.model +'&id=' + (this.view.datarecord.id || '') + '&field=' + this.name + '&t=' + (new Date().getTime())
|
||||
this.$image.attr('src', url);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2176,8 +2218,10 @@ openerp.base.form.widgets = new openerp.base.Registry({
|
||||
'url' : 'openerp.base.form.FieldUrl',
|
||||
'text' : 'openerp.base.form.FieldText',
|
||||
'text_wiki' : 'openerp.base.form.FieldText',
|
||||
'date' : 'openerp.base.form.FieldDate',
|
||||
'datetime' : 'openerp.base.form.FieldDatetime',
|
||||
// 'date' : 'openerp.base.form.FieldDate',
|
||||
// 'datetime' : 'openerp.base.form.FieldDatetime',
|
||||
'date' : 'openerp.base.form.FieldChar',
|
||||
'datetime' : 'openerp.base.form.FieldChar',
|
||||
'selection' : 'openerp.base.form.FieldSelection',
|
||||
'many2one' : 'openerp.base.form.FieldMany2One',
|
||||
'many2many' : 'openerp.base.form.FieldMany2Many',
|
||||
|
||||
@@ -103,18 +103,27 @@ openerp.base.list.editable = function (openerp) {
|
||||
* Checks if a record is being edited, and if so cancels it
|
||||
*/
|
||||
cancel_pending_edition: function () {
|
||||
var self = this, cancelled = $.Deferred();
|
||||
if (!this.edition) {
|
||||
return;
|
||||
cancelled.resolve();
|
||||
return cancelled.promise();
|
||||
}
|
||||
|
||||
if (this.edition_index !== null) {
|
||||
this.reload_record(this.edition_index);
|
||||
this.reload_record(this.edition_index, true).then(function () {
|
||||
cancelled.resolve();
|
||||
});
|
||||
} else {
|
||||
cancelled.resolve();
|
||||
}
|
||||
this.edition_form.stop();
|
||||
this.edition_form.$element.remove();
|
||||
delete this.edition_form;
|
||||
delete this.edition_index;
|
||||
delete this.edition;
|
||||
cancelled.then(function () {
|
||||
self.edition_form.stop();
|
||||
self.edition_form.$element.remove();
|
||||
delete self.edition_form;
|
||||
delete self.edition_index;
|
||||
delete self.edition;
|
||||
});
|
||||
return cancelled.promise();
|
||||
},
|
||||
/**
|
||||
* Adapts this list's view description to be suitable to the inner form view of a row being edited.
|
||||
@@ -134,66 +143,66 @@ openerp.base.list.editable = function (openerp) {
|
||||
return view;
|
||||
},
|
||||
render_row_as_form: function (row) {
|
||||
this.cancel_pending_edition();
|
||||
|
||||
var self = this;
|
||||
var $new_row = $('<tr>', {
|
||||
id: _.uniqueId('oe-editable-row-'),
|
||||
'class': $(row).attr('class'),
|
||||
click: function (e) {e.stopPropagation();}
|
||||
})
|
||||
.delegate('button.oe-edit-row-save', 'click', function () {
|
||||
self.save_row();
|
||||
})
|
||||
.delegate('button.oe-edit-row-cancel', 'click', function () {
|
||||
self.cancel_edition();
|
||||
})
|
||||
.delegate('button', 'keyup', function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
})
|
||||
.keyup(function (e) {
|
||||
switch (e.which) {
|
||||
case KEY_RETURN:
|
||||
self.save_row(true);
|
||||
break;
|
||||
case KEY_ESCAPE:
|
||||
self.cancel_edition();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (row) {
|
||||
$new_row.replaceAll(row);
|
||||
} else if (this.options.editable === 'top') {
|
||||
this.$current.prepend($new_row);
|
||||
} else if (this.options.editable) {
|
||||
this.$current.append($new_row);
|
||||
}
|
||||
this.edition = true;
|
||||
this.edition_index = this.dataset.index;
|
||||
this.edition_form = _.extend(new openerp.base.FormView(
|
||||
null, this.group.view.session, $new_row.attr('id'),
|
||||
this.dataset, false), {
|
||||
template: 'ListView.row.form',
|
||||
registry: openerp.base.list.form.widgets
|
||||
});
|
||||
$.when(this.edition_form.on_loaded({fields_view: this.get_form_fields_view()})).then(function () {
|
||||
// put in $.when just in case FormView.on_loaded becomes asynchronous
|
||||
$new_row.find('td')
|
||||
.addClass('oe-field-cell')
|
||||
.removeAttr('width')
|
||||
.end()
|
||||
.find('td:first').removeClass('oe-field-cell').end()
|
||||
.find('td:last').removeClass('oe-field-cell').end();
|
||||
// pad in case of groupby
|
||||
_(self.columns).each(function (column) {
|
||||
if (column.meta) {
|
||||
$new_row.prepend('<td>');
|
||||
}
|
||||
this.cancel_pending_edition().then(function () {
|
||||
var $new_row = $('<tr>', {
|
||||
id: _.uniqueId('oe-editable-row-'),
|
||||
'class': $(row).attr('class'),
|
||||
click: function (e) {e.stopPropagation();}
|
||||
})
|
||||
.delegate('button.oe-edit-row-save', 'click', function () {
|
||||
self.save_row();
|
||||
})
|
||||
.delegate('button.oe-edit-row-cancel', 'click', function () {
|
||||
self.cancel_edition();
|
||||
})
|
||||
.delegate('button', 'keyup', function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
})
|
||||
.keyup(function (e) {
|
||||
switch (e.which) {
|
||||
case KEY_RETURN:
|
||||
self.save_row(true);
|
||||
break;
|
||||
case KEY_ESCAPE:
|
||||
self.cancel_edition();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (row) {
|
||||
$new_row.replaceAll(row);
|
||||
} else if (self.options.editable === 'top') {
|
||||
self.$current.prepend($new_row);
|
||||
} else if (self.options.editable) {
|
||||
self.$current.append($new_row);
|
||||
}
|
||||
self.edition = true;
|
||||
self.edition_index = self.dataset.index;
|
||||
self.edition_form = _.extend(new openerp.base.FormView(
|
||||
null, self.group.view.session, $new_row.attr('id'),
|
||||
self.dataset, false), {
|
||||
template: 'ListView.row.form',
|
||||
registry: openerp.base.list.form.widgets
|
||||
});
|
||||
$.when(self.edition_form.on_loaded({fields_view: self.get_form_fields_view()})).then(function () {
|
||||
// put in $.when just in case FormView.on_loaded becomes asynchronous
|
||||
$new_row.find('td')
|
||||
.addClass('oe-field-cell')
|
||||
.removeAttr('width')
|
||||
.end()
|
||||
.find('td:first').removeClass('oe-field-cell').end()
|
||||
.find('td:last').removeClass('oe-field-cell').end();
|
||||
// pad in case of groupby
|
||||
_(self.columns).each(function (column) {
|
||||
if (column.meta) {
|
||||
$new_row.prepend('<td>');
|
||||
}
|
||||
});
|
||||
|
||||
self.edition_form.do_show();
|
||||
self.edition_form.do_show();
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -205,12 +214,7 @@ openerp.base.list.editable = function (openerp) {
|
||||
save_row: function (edit_next) {
|
||||
var self = this;
|
||||
this.edition_form.do_save(function (result) {
|
||||
self.reload_record(self.dataset.index, true).then(function () {
|
||||
self.edition_form.stop();
|
||||
delete self.edition_form;
|
||||
delete self.edition_index;
|
||||
delete self.edition;
|
||||
|
||||
self.cancel_pending_edition().then(function () {
|
||||
$(self).trigger('saved', [self.dataset]);
|
||||
if (!edit_next) {
|
||||
return;
|
||||
|
||||
@@ -24,24 +24,37 @@ openerp.base.list = {
|
||||
].join('')
|
||||
}
|
||||
|
||||
var record = row_data[column.id];
|
||||
if (record.value === false) {
|
||||
return value_if_empty === undefined ? '' : value_if_empty;
|
||||
var value = row_data[column.id].value;
|
||||
|
||||
// If NaN value, display as with a `false` (empty cell)
|
||||
if (typeof value === 'number' && isNaN(value)) {
|
||||
value = false;
|
||||
}
|
||||
switch (value) {
|
||||
case false:
|
||||
case Infinity:
|
||||
case -Infinity:
|
||||
return value_if_empty === undefined ? '' : value_if_empty;
|
||||
}
|
||||
switch (column.widget || column.type) {
|
||||
case 'many2one':
|
||||
// name_get value format
|
||||
return record.value[1];
|
||||
case 'integer':
|
||||
return _.sprintf('%d', value);
|
||||
case 'float':
|
||||
var precision = column.digits ? column.digits[1] : 2;
|
||||
return _.sprintf('%.' + precision + 'f', value);
|
||||
case 'float_time':
|
||||
return _.sprintf("%02d:%02d",
|
||||
Math.floor(record.value),
|
||||
Math.round((record.value % 1) * 60));
|
||||
Math.floor(value),
|
||||
Math.round((value % 1) * 60));
|
||||
case 'progressbar':
|
||||
return _.sprintf(
|
||||
'<progress value="%.2f" max="100.0">%.2f%%</progress>',
|
||||
record.value, record.value);
|
||||
value, value);
|
||||
case 'many2one':
|
||||
// name_get value format
|
||||
return value[1];
|
||||
default:
|
||||
return record.value;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -87,9 +100,9 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
*
|
||||
* @borrows openerp.base.ActionExecutor#execute_action as #execute_action
|
||||
*/
|
||||
init: function(view_manager, session, element_id, dataset, view_id, options) {
|
||||
this._super(session, element_id);
|
||||
this.view_manager = view_manager || new openerp.base.NullViewManager();
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
@@ -100,7 +113,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
this.flags = this.view_manager.flags || {};
|
||||
|
||||
this.set_groups(new openerp.base.ListView.Groups(this));
|
||||
|
||||
|
||||
if (this.dataset instanceof openerp.base.DataSetStatic) {
|
||||
this.groups.datagroup = new openerp.base.StaticDataGroup(this.dataset);
|
||||
}
|
||||
@@ -254,8 +267,9 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
})
|
||||
.val(self._limit || 'NaN');
|
||||
});
|
||||
if(this.view_manager.sidebar)
|
||||
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar);
|
||||
|
||||
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar);
|
||||
},
|
||||
/**
|
||||
* Configures the ListView pager based on the provided dataset's information
|
||||
@@ -347,16 +361,10 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
}
|
||||
var aggregation_func = column['group_operator'] || 'sum';
|
||||
|
||||
if (!column[aggregation_func]) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
field: column.id,
|
||||
type: column.type,
|
||||
return _.extend({}, column, {
|
||||
'function': aggregation_func,
|
||||
label: column[aggregation_func]
|
||||
};
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -386,11 +394,12 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
if (this.hidden) {
|
||||
this.$element.find('table').append(
|
||||
this.$element.find('.oe-listview-content').append(
|
||||
this.groups.apoptosis().render());
|
||||
this.hidden = false;
|
||||
}
|
||||
this.view_manager.sidebar.do_refresh(true);
|
||||
if(this.view_manager.sidebar)
|
||||
this.view_manager.sidebar.do_refresh(true);
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
@@ -421,7 +430,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
* re-renders the content of the list view
|
||||
*/
|
||||
reload_content: function () {
|
||||
this.$element.find('table').append(
|
||||
this.$element.find('.oe-listview-content').append(
|
||||
this.groups.apoptosis().render(
|
||||
$.proxy(this, 'compute_aggregates')));
|
||||
},
|
||||
@@ -451,7 +460,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
this.dataset.context = results.context;
|
||||
this.dataset.domain = results.domain;
|
||||
this.groups.datagroup = new openerp.base.DataGroup(
|
||||
this.session, this.model,
|
||||
this, this.model,
|
||||
results.domain, results.context,
|
||||
results.group_by);
|
||||
this.groups.datagroup.sort = this.dataset._sort;
|
||||
@@ -475,6 +484,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
var self = this;
|
||||
return $.when(this.dataset.unlink(ids)).then(function () {
|
||||
self.groups.drop_records(ids);
|
||||
self.compute_aggregates();
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -503,11 +513,17 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
* @param {Function} callback should be called after the action is executed, if non-null
|
||||
*/
|
||||
do_action: function (name, id, callback) {
|
||||
var action = _.detect(this.columns, function (field) {
|
||||
var self = this,
|
||||
action = _.detect(this.columns, function (field) {
|
||||
return field.name === name;
|
||||
});
|
||||
if (!action) { return; }
|
||||
this.execute_action(action, this.dataset, this.session.action_manager, id, callback);
|
||||
this.execute_action(
|
||||
action, this.dataset, this.session.action_manager, id, function () {
|
||||
$.when(callback.apply(this, arguments).then(function () {
|
||||
self.compute_aggregates();
|
||||
}));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Handles the activation of a record (clicking on it)
|
||||
@@ -554,7 +570,6 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
compute_aggregates: function (records) {
|
||||
var columns = _(this.aggregate_columns).filter(function (column) {
|
||||
return column['function']; });
|
||||
|
||||
if (_.isEmpty(columns)) { return; }
|
||||
|
||||
if (_.isEmpty(records)) {
|
||||
@@ -562,17 +577,39 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
}
|
||||
|
||||
var count = 0, sums = {};
|
||||
_(columns).each(function (column) { sums[column.field] = 0; });
|
||||
_(columns).each(function (column) {
|
||||
switch (column['function']) {
|
||||
case 'max':
|
||||
sums[column.id] = -Infinity;
|
||||
break;
|
||||
case 'min':
|
||||
sums[column.id] = Infinity;
|
||||
break;
|
||||
default:
|
||||
sums[column.id] = 0;
|
||||
}
|
||||
});
|
||||
_(records).each(function (record) {
|
||||
count += record.count || 1;
|
||||
_(columns).each(function (column) {
|
||||
var field = column.field;
|
||||
var field = column.id,
|
||||
value = record.values[field];
|
||||
switch (column['function']) {
|
||||
case 'sum':
|
||||
sums[field] += record.values[field];
|
||||
sums[field] += value;
|
||||
break;
|
||||
case 'avg':
|
||||
sums[field] += record.count * record.values[field];
|
||||
sums[field] += record.count * value;
|
||||
break;
|
||||
case 'min':
|
||||
if (sums[field] > value) {
|
||||
sums[field] = value;
|
||||
}
|
||||
break;
|
||||
case 'max':
|
||||
if (sums[field] < value) {
|
||||
sums[field] = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -580,14 +617,13 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
|
||||
var aggregates = {};
|
||||
_(columns).each(function (column) {
|
||||
var field = column.field;
|
||||
var field = column.id;
|
||||
switch (column['function']) {
|
||||
case 'sum':
|
||||
aggregates[field] = sums[field];
|
||||
break;
|
||||
case 'avg':
|
||||
aggregates[field] = sums[field] / count;
|
||||
aggregates[field] = {value: sums[field] / count};
|
||||
break;
|
||||
default:
|
||||
aggregates[field] = {value: sums[field]};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -599,14 +635,14 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
if (!column['function']) {
|
||||
return;
|
||||
}
|
||||
var pattern = (column.type == 'integer') ? '%d' : '%.2f';
|
||||
$footer_cells.filter(_.sprintf('[data-field=%s]', column.field))
|
||||
.text(_.sprintf(pattern, aggregation[column.field]));
|
||||
|
||||
$footer_cells.filter(_.sprintf('[data-field=%s]', column.id))
|
||||
.html(openerp.base.list.render_cell(aggregation, column));
|
||||
});
|
||||
}
|
||||
// TODO: implement reorder (drag and drop rows)
|
||||
});
|
||||
openerp.base.ListView.List = Class.extend( /** @lends openerp.base.ListView.List# */{
|
||||
openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.ListView.List# */{
|
||||
/**
|
||||
* List display for the ListView, handles basic DOM events and transforms
|
||||
* them in the relevant higher-level events, to which the list view (or
|
||||
@@ -666,7 +702,7 @@ openerp.base.ListView.List = Class.extend( /** @lends openerp.base.ListView.List
|
||||
index = self.row_position($row);
|
||||
|
||||
$(self).trigger('action', [field, record_id, function () {
|
||||
self.reload_record(index, true);
|
||||
return self.reload_record(index, true);
|
||||
}]);
|
||||
})
|
||||
.delegate('tr', 'click', function (e) {
|
||||
@@ -804,7 +840,7 @@ openerp.base.ListView.List = Class.extend( /** @lends openerp.base.ListView.List
|
||||
|
||||
return $.when(read_p).then(function () {
|
||||
self.$current.children().eq(record_index)
|
||||
.replaceWith(self.render_record(record_index)); })
|
||||
.replaceWith(self.render_record(record_index)); });
|
||||
},
|
||||
/**
|
||||
* Renders a list record to HTML
|
||||
@@ -842,7 +878,7 @@ openerp.base.ListView.List = Class.extend( /** @lends openerp.base.ListView.List
|
||||
}
|
||||
// drag and drop
|
||||
});
|
||||
openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Groups# */{
|
||||
openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.base.ListView.Groups# */{
|
||||
passtrough_events: 'action deleted row_link',
|
||||
/**
|
||||
* Grouped display for the ListView. Handles basic DOM events and interacts
|
||||
@@ -979,8 +1015,8 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
||||
row_data[group.grouped_on] = group;
|
||||
var group_column = _(self.columns).detect(function (column) {
|
||||
return column.id === group.grouped_on; });
|
||||
$group_column.text(openerp.base.list.render_cell(
|
||||
row_data, group_column, "Undefined"
|
||||
$group_column.html(openerp.base.list.render_cell(
|
||||
row_data, group_column, "Undefined"
|
||||
));
|
||||
if (group.openable) {
|
||||
// Make openable if not terminal group & group_by_no_leaf
|
||||
@@ -1084,6 +1120,45 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
||||
});
|
||||
return d.promise();
|
||||
},
|
||||
setup_resequence_rows: function (list, dataset) {
|
||||
// drag and drop enabled if list is not sorted and there is a
|
||||
// "sequence" column in the view.
|
||||
if ((dataset.sort && dataset.sort())
|
||||
|| !_(this.columns).any(function (column) {
|
||||
return column.name === 'sequence'; })) {
|
||||
return;
|
||||
}
|
||||
// ondrop, move relevant record & fix sequences
|
||||
list.$current.sortable({
|
||||
stop: function (event, ui) {
|
||||
var from = ui.item.data('index'),
|
||||
to = ui.item.prev().data('index') || 0;
|
||||
if (from === to) { return; }
|
||||
list.rows.splice(to, 0, list.rows.splice(from, 1)[0]);
|
||||
|
||||
ui.item.parent().children().each(function (i, e) {
|
||||
// reset record-index accelerators on rows and even/odd
|
||||
var even = i%2 === 0;
|
||||
$(e).data('index', i)
|
||||
.toggleClass('even', even)
|
||||
.toggleClass('odd', !even);
|
||||
});
|
||||
|
||||
// resequencing time!
|
||||
var data, index = to,
|
||||
// if drag to 1st row (to = 0), start sequencing from 0
|
||||
// (exclusive lower bound)
|
||||
seq = to ? list.rows[to - 1].data.sequence.value : 0;
|
||||
while (++seq, data = list.rows[index++].data) {
|
||||
data.sequence.value = seq;
|
||||
// write are independent from one another, so we can just
|
||||
// launch them all at the same time and we don't really
|
||||
// give a fig about when they're done
|
||||
dataset.write(data.id.value, {sequence: seq});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
render: function (post_render) {
|
||||
var self = this;
|
||||
var $element = $('<tbody>');
|
||||
@@ -1102,6 +1177,7 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr
|
||||
self.children[null] = list;
|
||||
self.elements =
|
||||
[list.$current.replaceAll($element)[0]];
|
||||
self.setup_resequence_rows(list, dataset);
|
||||
if (post_render) { post_render(); }
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
openerp.base.search = function(openerp) {
|
||||
|
||||
openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
init: function(view_manager, session, element_id, dataset, view_id, defaults) {
|
||||
this._super(session, element_id);
|
||||
this.view_manager = view_manager || new openerp.base.NullViewManager();
|
||||
init: function(parent, element_id, dataset, view_id, defaults) {
|
||||
this._super(parent, element_id);
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
this.view_id = view_id;
|
||||
@@ -14,10 +14,13 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
this.enabled_filters = [];
|
||||
|
||||
this.has_focus = false;
|
||||
|
||||
this.ready = $.Deferred();
|
||||
},
|
||||
start: function() {
|
||||
//this.log('Starting SearchView '+this.model+this.view_id)
|
||||
return this.rpc("/base/searchview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded);
|
||||
this.rpc("/base/searchview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded);
|
||||
return this.ready.promise();
|
||||
},
|
||||
show: function () {
|
||||
this.$element.show();
|
||||
@@ -107,12 +110,13 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
}
|
||||
},
|
||||
on_loaded: function(data) {
|
||||
var lines = this.make_widgets(
|
||||
data.fields_view['arch'].children,
|
||||
data.fields_view.fields);
|
||||
var self = this,
|
||||
lines = this.make_widgets(
|
||||
data.fields_view['arch'].children,
|
||||
data.fields_view.fields);
|
||||
|
||||
// for extended search view
|
||||
var ext = new openerp.base.search.ExtendedSearch(null, this.session, this.model);
|
||||
var ext = new openerp.base.search.ExtendedSearch(this, this.model);
|
||||
lines.push([ext]);
|
||||
this.inputs.push(ext);
|
||||
|
||||
@@ -121,6 +125,7 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
'lines': lines,
|
||||
'defaults': this.defaults
|
||||
});
|
||||
|
||||
// We don't understand why the following commented line does not work in Chrome but
|
||||
// the non-commented line does. As far as we investigated, only God knows.
|
||||
//this.$element.html(render);
|
||||
@@ -132,30 +137,90 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
.submit(this.do_search)
|
||||
.bind('reset', this.do_clear);
|
||||
// start() all the widgets
|
||||
_(lines).chain().flatten().each(function (widget) {
|
||||
widget.start();
|
||||
var widget_starts = _(lines).chain().flatten().map(function (widget) {
|
||||
return widget.start();
|
||||
}).value();
|
||||
|
||||
$.when.apply(null, widget_starts).then(function () {
|
||||
self.ready.resolve();
|
||||
});
|
||||
|
||||
// filters management
|
||||
this.$element.find(".oe_search-view-filters-management").change(this.on_filters_management);
|
||||
this.reload_managed_filters();
|
||||
},
|
||||
reload_managed_filters: function() {
|
||||
var self = this;
|
||||
return this.rpc('/base/searchview/get_filters', {
|
||||
model: this.dataset.model
|
||||
}).then(function(result) {
|
||||
self.managed_filters = result;
|
||||
var filters = self.$element.find(".oe_search-view-filters-management");
|
||||
filters.html(QWeb.render("SearchView.managed-filters", {filters: result}));
|
||||
filters.change(self.on_filters_management);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Handle event when the user make a selection in the filters management select box.
|
||||
*/
|
||||
on_filters_management: function(e) {
|
||||
var self = this;
|
||||
var select = this.$element.find(".oe_search-view-filters-management");
|
||||
var val = select.val();
|
||||
select.val("_filters");
|
||||
|
||||
if (val.slice(0,1) == "_") // useless action
|
||||
if (val.slice(0,1) == "_") { // useless action
|
||||
select.val("_filters");
|
||||
return;
|
||||
}
|
||||
if (val.slice(0, "get:".length) == "get:") {
|
||||
val = val.slice("get:".length);
|
||||
//TODO niv
|
||||
val = parseInt(val);
|
||||
var filter = this.managed_filters[val];
|
||||
this.on_search([filter.domain], [filter.context], []);
|
||||
} else if (val == "save_filter") {
|
||||
//TODO niv
|
||||
select.val("_filters");
|
||||
var data = this.build_search_data();
|
||||
var context = new openerp.base.CompoundContext();
|
||||
_.each(data.contexts, function(x) {
|
||||
context.add(x);
|
||||
});
|
||||
var domain = new openerp.base.CompoundDomain();
|
||||
_.each(data.domains, function(x) {
|
||||
domain.add(x);
|
||||
});
|
||||
var dial_html = QWeb.render("SearchView.managed-filters.add");
|
||||
var $dial = $(dial_html);
|
||||
$dial.dialog({
|
||||
modal: true,
|
||||
title: "Filter Entry",
|
||||
buttons: {
|
||||
Cancel: function() {
|
||||
$(this).dialog("close");
|
||||
},
|
||||
OK: function() {
|
||||
$(this).dialog("close");
|
||||
var name = $(this).find("input").val();
|
||||
self.rpc('/base/searchview/save_filter', {
|
||||
model: self.dataset.model,
|
||||
context_to_save: context,
|
||||
domain: domain,
|
||||
name: name
|
||||
}).then(function(result) {
|
||||
self.reload_managed_filters();
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
} else { // manage_filters
|
||||
//TODO niv
|
||||
select.val("_filters");
|
||||
this.do_action({
|
||||
res_model: 'ir.filters',
|
||||
views: [[false, 'list'], [false, 'form']],
|
||||
type: 'ir.actions.act_window',
|
||||
context: {"search_default_user_id": this.session.uid,
|
||||
"search_default_model_id": this.dataset.model},
|
||||
target: "current",
|
||||
limit : 80,
|
||||
auto_search : true
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -170,11 +235,25 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
* @param e jQuery event object coming from the "Search" button
|
||||
*/
|
||||
do_search: function (e) {
|
||||
// reset filters management
|
||||
var select = this.$element.find(".oe_search-view-filters-management");
|
||||
select.val("_filters");
|
||||
|
||||
if (e && e.preventDefault) { e.preventDefault(); }
|
||||
|
||||
var domains = [], contexts = [];
|
||||
var data = this.build_search_data();
|
||||
|
||||
var errors = [];
|
||||
if (data.errors.length) {
|
||||
this.on_invalid(data.errors);
|
||||
return;
|
||||
}
|
||||
|
||||
this.on_search(data.domains, data.contexts, data.groupbys);
|
||||
},
|
||||
build_search_data: function() {
|
||||
var domains = [],
|
||||
contexts = [],
|
||||
errors = [];
|
||||
|
||||
_.each(this.inputs, function (input) {
|
||||
try {
|
||||
@@ -196,19 +275,13 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
}
|
||||
});
|
||||
|
||||
if (errors.length) {
|
||||
this.on_invalid(errors);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: do we need to handle *fields* with group_by in their context?
|
||||
var groupbys = _(this.enabled_filters)
|
||||
.chain()
|
||||
.map(function (filter) { return filter.get_context();})
|
||||
.compact()
|
||||
.value();
|
||||
|
||||
this.on_search(domains, contexts, groupbys);
|
||||
return {domains: domains, contexts: contexts, errors: errors, groupbys: groupbys};
|
||||
},
|
||||
/**
|
||||
* Triggered after the SearchView has collected all relevant domains and
|
||||
@@ -293,8 +366,7 @@ openerp.base.search.fields = new openerp.base.Registry({
|
||||
'many2one': 'openerp.base.search.ManyToOneField',
|
||||
'many2many': 'openerp.base.search.ManyToManyField'
|
||||
});
|
||||
openerp.base.search.Invalid = Class.extend(
|
||||
/** @lends openerp.base.search.Invalid# */{
|
||||
openerp.base.search.Invalid = openerp.base.Class.extend( /** @lends openerp.base.search.Invalid# */{
|
||||
/**
|
||||
* Exception thrown by search widgets when they hold invalid values,
|
||||
* which they can not return when asked.
|
||||
@@ -314,8 +386,7 @@ openerp.base.search.Invalid = Class.extend(
|
||||
': [' + this.value + '] is ' + this.message);
|
||||
}
|
||||
});
|
||||
openerp.base.search.Widget = openerp.base.Controller.extend(
|
||||
/** @lends openerp.base.search.Widget# */{
|
||||
openerp.base.search.Widget = openerp.base.Controller.extend( /** @lends openerp.base.search.Widget# */{
|
||||
template: null,
|
||||
/**
|
||||
* Root class of all search widgets
|
||||
@@ -395,8 +466,6 @@ openerp.base.search.add_expand_listener = function($root) {
|
||||
};
|
||||
openerp.base.search.Group = openerp.base.search.Widget.extend({
|
||||
template: 'SearchView.group',
|
||||
// TODO: contain stuff
|
||||
// TODO: @expand
|
||||
init: function (view_section, view, fields) {
|
||||
this._super(view);
|
||||
this.attrs = view_section.attrs;
|
||||
@@ -414,8 +483,7 @@ openerp.base.search.Group = openerp.base.search.Widget.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.search.Input = openerp.base.search.Widget.extend(
|
||||
/** @lends openerp.base.search.Input# */{
|
||||
openerp.base.search.Input = openerp.base.search.Widget.extend( /** @lends openerp.base.search.Input# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @extends openerp.base.search.Widget
|
||||
@@ -437,7 +505,6 @@ openerp.base.search.Input = openerp.base.search.Widget.extend(
|
||||
});
|
||||
openerp.base.search.Filter = openerp.base.search.Input.extend({
|
||||
template: 'SearchView.filter',
|
||||
// TODO: force rendering
|
||||
init: function (node, view) {
|
||||
this._super(view);
|
||||
this.attrs = node.attrs;
|
||||
@@ -486,13 +553,9 @@ openerp.base.search.Filter = openerp.base.search.Input.extend({
|
||||
return this.attrs.domain;
|
||||
}
|
||||
});
|
||||
openerp.base.search.Field = openerp.base.search.Input.extend(
|
||||
/** @lends openerp.base.search.Field# */ {
|
||||
openerp.base.search.Field = openerp.base.search.Input.extend( /** @lends openerp.base.search.Field# */ {
|
||||
template: 'SearchView.field',
|
||||
default_operator: '=',
|
||||
// TODO: set default values
|
||||
// TODO: get context, domain
|
||||
// TODO: holds Filters
|
||||
/**
|
||||
* @constructs
|
||||
* @extends openerp.base.search.Input
|
||||
@@ -530,9 +593,7 @@ openerp.base.search.Field = openerp.base.search.Input.extend(
|
||||
},
|
||||
get_domain: function () {
|
||||
var val = this.get_value();
|
||||
|
||||
var has_value = (val !== null && val !== '');
|
||||
if(!has_value) {
|
||||
if (val === null || val === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -544,9 +605,7 @@ openerp.base.search.Field = openerp.base.search.Input.extend(
|
||||
this.get_value()
|
||||
]];
|
||||
}
|
||||
return _.extend(
|
||||
{}, domain,
|
||||
{own_values: {self: val}});
|
||||
return _.extend({}, domain, {own_values: {self: val}});
|
||||
}
|
||||
});
|
||||
/**
|
||||
@@ -559,8 +618,7 @@ openerp.base.search.Field = openerp.base.search.Input.extend(
|
||||
* @class
|
||||
* @extends openerp.base.search.Field
|
||||
*/
|
||||
openerp.base.search.CharField = openerp.base.search.Field.extend(
|
||||
/** @lends openerp.base.search.CharField# */ {
|
||||
openerp.base.search.CharField = openerp.base.search.Field.extend( /** @lends openerp.base.search.CharField# */ {
|
||||
default_operator: 'ilike',
|
||||
get_value: function () {
|
||||
return this.$element.val();
|
||||
@@ -599,32 +657,40 @@ openerp.base.search.BooleanField = openerp.base.search.Field.extend({
|
||||
}
|
||||
}
|
||||
});
|
||||
openerp.base.search.IntegerField = openerp.base.search.Field.extend({
|
||||
openerp.base.search.NumberField = openerp.base.search.Field.extend(/** @lends openerp.base.search.NumberField# */{
|
||||
get_value: function () {
|
||||
if (!this.$element.val()) {
|
||||
return null;
|
||||
}
|
||||
var val = parseInt(this.$element.val());
|
||||
var check = Number(this.$element.val());
|
||||
if (isNaN(check) || val !== check) {
|
||||
var val = this.parse(this.$element.val()),
|
||||
check = Number(this.$element.val());
|
||||
if (isNaN(val) || val !== check) {
|
||||
this.$element.addClass('error');
|
||||
throw new openerp.base.search.Invalid(
|
||||
this.attrs.name, this.$element.val(), "not a valid integer");
|
||||
this.attrs.name, this.$element.val(), this.error_message);
|
||||
}
|
||||
this.$element.removeClass('error');
|
||||
return val;
|
||||
}
|
||||
});
|
||||
openerp.base.search.FloatField = openerp.base.search.Field.extend({
|
||||
get_value: function () {
|
||||
var val = Number(this.$element.val());
|
||||
if (isNaN(val)) {
|
||||
this.$element.addClass('error');
|
||||
throw new openerp.base.search.Invalid(
|
||||
this.attrs.name, this.$element.val(), "not a valid number");
|
||||
}
|
||||
this.$element.removeClass('error');
|
||||
return val;
|
||||
/**
|
||||
* @class
|
||||
* @extends openerp.base.search.NumberField
|
||||
*/
|
||||
openerp.base.search.IntegerField = openerp.base.search.NumberField.extend(/** @lends openerp.base.search.IntegerField# */{
|
||||
error_message: "not a valid integer",
|
||||
parse: function (value) {
|
||||
return parseInt(value, 10);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* @class
|
||||
* @extends openerp.base.search.NumberField
|
||||
*/
|
||||
openerp.base.search.FloatField = openerp.base.search.NumberField.extend(/** @lends openerp.base.search.FloatField# */{
|
||||
error_message: "not a valid number",
|
||||
parse: function (value) {
|
||||
return parseFloat(value);
|
||||
}
|
||||
});
|
||||
openerp.base.search.SelectionField = openerp.base.search.Field.extend({
|
||||
@@ -633,12 +699,7 @@ openerp.base.search.SelectionField = openerp.base.search.Field.extend({
|
||||
return this.$element.val();
|
||||
}
|
||||
});
|
||||
/**
|
||||
* @class
|
||||
* @extends openerp.base.search.Field
|
||||
*/
|
||||
openerp.base.search.DateField = openerp.base.search.Field.extend(
|
||||
/** @lends openerp.base.search.DateField# */{
|
||||
openerp.base.search.DateField = openerp.base.search.Field.extend( /** @lends openerp.base.search.DateField# */{
|
||||
template: 'SearchView.fields.date',
|
||||
/**
|
||||
* enables date picker on the HTML widgets
|
||||
@@ -663,8 +724,12 @@ openerp.base.search.DateField = openerp.base.search.Field.extend(
|
||||
get_values: function () {
|
||||
var values_array = this.$element.find('input').serializeArray();
|
||||
|
||||
var from = values_array[0].value;
|
||||
var to = values_array[1].value;
|
||||
if (!values_array || !values_array[0]) {
|
||||
throw new openerp.base.search.Invalid(
|
||||
this.attrs.name, null, "widget not ready");
|
||||
}
|
||||
var from = values_array[0].value,
|
||||
to = values_array[1].value;
|
||||
|
||||
var field_values = {};
|
||||
if (from) {
|
||||
@@ -709,22 +774,88 @@ openerp.base.search.DateField = openerp.base.search.Field.extend(
|
||||
openerp.base.search.DateTimeField = openerp.base.search.DateField.extend({
|
||||
// TODO: time?
|
||||
});
|
||||
openerp.base.search.OneToManyField = openerp.base.search.IntegerField.extend({
|
||||
openerp.base.search.OneToManyField = openerp.base.search.CharField.extend({
|
||||
// TODO: .relation, .context, .domain
|
||||
});
|
||||
openerp.base.search.ManyToOneField = openerp.base.search.IntegerField.extend({
|
||||
openerp.base.search.ManyToOneField = openerp.base.search.CharField.extend({
|
||||
// TODO: @widget
|
||||
// TODO: .relation, .selection, .context, .domain
|
||||
init: function (view_section, field, view) {
|
||||
this._super(view_section, field, view);
|
||||
var self = this;
|
||||
this.got_name = $.Deferred().then(function () {
|
||||
self.$element.val(self.name);
|
||||
});
|
||||
this.dataset = new openerp.base.DataSet(
|
||||
this.view, this.attrs['relation']);
|
||||
},
|
||||
start: function () {
|
||||
this._super();
|
||||
this.setup_autocomplete();
|
||||
var started = $.Deferred();
|
||||
this.got_name.then(function () { started.resolve();},
|
||||
function () { started.resolve(); });
|
||||
return started.promise();
|
||||
},
|
||||
setup_autocomplete: function () {
|
||||
var self = this;
|
||||
this.$element.autocomplete({
|
||||
source: function (req, resp) {
|
||||
self.dataset.name_search(
|
||||
req.term, self.attrs.domain, 'ilike', 8, function (data) {
|
||||
resp(_.map(data, function (result) {
|
||||
return {id: result[0], label: result[1]}
|
||||
}));
|
||||
});
|
||||
},
|
||||
select: function (event, ui) {
|
||||
self.id = ui.item.id;
|
||||
self.name = ui.item.label;
|
||||
},
|
||||
delay: 0
|
||||
})
|
||||
},
|
||||
on_name_get: function (name_get) {
|
||||
if (!name_get.length) {
|
||||
delete this.id;
|
||||
this.got_name.reject();
|
||||
return;
|
||||
}
|
||||
this.name = name_get[0][1];
|
||||
this.got_name.resolve();
|
||||
},
|
||||
render: function (defaults) {
|
||||
if (defaults[this.attrs.name]) {
|
||||
this.id = defaults[this.attrs.name];
|
||||
// TODO: maybe this should not be completely removed
|
||||
delete defaults[this.attrs.name];
|
||||
this.dataset.name_get([this.id], $.proxy(this, 'on_name_get'));
|
||||
} else {
|
||||
this.got_name.reject();
|
||||
}
|
||||
return this._super(defaults);
|
||||
},
|
||||
get_domain: function () {
|
||||
if (this.id && this.name) {
|
||||
if (this.$element.val() === this.name) {
|
||||
return [[this.attrs.name, '=', this.id]];
|
||||
} else {
|
||||
delete this.id;
|
||||
delete this.name;
|
||||
}
|
||||
}
|
||||
return this._super();
|
||||
}
|
||||
});
|
||||
openerp.base.search.ManyToManyField = openerp.base.search.IntegerField.extend({
|
||||
openerp.base.search.ManyToManyField = openerp.base.search.CharField.extend({
|
||||
// TODO: .related_columns (Array), .context, .domain
|
||||
});
|
||||
|
||||
openerp.base.search.ExtendedSearch = openerp.base.BaseWidget.extend({
|
||||
template: 'SearchView.extended_search',
|
||||
identifier_prefix: 'extended-search',
|
||||
init: function (parent, session, model) {
|
||||
this._super(parent, session);
|
||||
init: function (parent, model) {
|
||||
this._super(parent);
|
||||
this.model = model;
|
||||
},
|
||||
add_group: function() {
|
||||
@@ -780,7 +911,9 @@ openerp.base.search.ExtendedSearch = openerp.base.BaseWidget.extend({
|
||||
},
|
||||
check_last_element: function() {
|
||||
_.each(this.children, function(x) {x.set_last_group(false);});
|
||||
this.children[this.children.length - 1].set_last_group(true);
|
||||
if (this.children.length >= 1) {
|
||||
this.children[this.children.length - 1].set_last_group(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -893,7 +1026,7 @@ openerp.base.search.ExtendedSearchProposition = openerp.base.BaseWidget.extend({
|
||||
if (! e instanceof openerp.base.KeyNotFound) {
|
||||
throw e;
|
||||
}
|
||||
var type = "char";
|
||||
type = "char";
|
||||
this.log('Unknow field type ' + e.key);
|
||||
}
|
||||
this.value = new (openerp.base.search.custom_filters.get_object(type))
|
||||
@@ -994,12 +1127,11 @@ openerp.base.search.ExtendedSearchProposition.Integer = openerp.base.BaseWidget.
|
||||
{value: "<=", text: "less or equal than"}
|
||||
],
|
||||
get_value: function() {
|
||||
val = this.$element.val();
|
||||
val2 = parseFloat(val);
|
||||
if(val2 != 0 && !val2) {
|
||||
var value = parseFloat(this.$element.val());
|
||||
if(value != 0 && !value) {
|
||||
return "";
|
||||
}
|
||||
return Math.round(val2);
|
||||
return Math.round(value);
|
||||
}
|
||||
});
|
||||
openerp.base.search.ExtendedSearchProposition.Float = openerp.base.BaseWidget.extend({
|
||||
@@ -1014,12 +1146,11 @@ openerp.base.search.ExtendedSearchProposition.Float = openerp.base.BaseWidget.ex
|
||||
{value: "<=", text: "less or equal than"}
|
||||
],
|
||||
get_value: function() {
|
||||
val = this.$element.val();
|
||||
val2 = parseFloat(val);
|
||||
if(val2 != 0 && !val2) {
|
||||
var value = parseFloat(this.$element.val());
|
||||
if(value != 0 && !value) {
|
||||
return "";
|
||||
}
|
||||
return val2;
|
||||
return value;
|
||||
}
|
||||
});
|
||||
openerp.base.search.ExtendedSearchProposition.Selection = openerp.base.BaseWidget.extend({
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*---------------------------------------------------------
|
||||
* OpenERP base library
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.base.view_help = function(openerp) {
|
||||
|
||||
openerp.base.ProcessView = openerp.base.Controller.extend({
|
||||
});
|
||||
|
||||
openerp.base.HelpView = openerp.base.Controller.extend({
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
|
||||
@@ -2,7 +2,7 @@
|
||||
* OpenERP base library
|
||||
*---------------------------------------------------------*/
|
||||
|
||||
openerp.base.tree = function(openerp) {
|
||||
openerp.base.view_tree = function(openerp) {
|
||||
|
||||
openerp.base.views.add('tree', 'openerp.base.TreeView');
|
||||
openerp.base.TreeView = openerp.base.Controller.extend({
|
||||
@@ -7,18 +7,30 @@ openerp.base.views = function(openerp) {
|
||||
openerp.base.client_actions = new openerp.base.Registry();
|
||||
openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
// process all kind of actions
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.viewmanager = null;
|
||||
this.current_dialog = null;
|
||||
// Temporary linking view_manager to session.
|
||||
// Will use controller_parent to find it when implementation will be done.
|
||||
session.action_manager = this;
|
||||
// Will use parent to find it when implementation will be done.
|
||||
this.session.action_manager = this;
|
||||
},
|
||||
/**
|
||||
* Process an action
|
||||
* Supported actions: act_window
|
||||
*/
|
||||
action_window: function() {
|
||||
},
|
||||
action_window_close: function() {
|
||||
},
|
||||
action_server: function() {
|
||||
},
|
||||
action_url: function() {
|
||||
},
|
||||
action_report: function() {
|
||||
},
|
||||
action_client: function() {
|
||||
},
|
||||
do_action: function(action, on_closed) {
|
||||
action.flags = _.extend({
|
||||
sidebar : action.target != 'new',
|
||||
@@ -41,7 +53,7 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
action.flags.new_window = true;
|
||||
}
|
||||
if (action.target == 'new') {
|
||||
var dialog = this.current_dialog = new openerp.base.ActionDialog(this.session, {
|
||||
var dialog = this.current_dialog = new openerp.base.ActionDialog(this, {
|
||||
title: action.name,
|
||||
width: '50%'
|
||||
});
|
||||
@@ -49,7 +61,7 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
dialog.close_callback = on_closed;
|
||||
}
|
||||
dialog.start(false);
|
||||
var viewmanager = dialog.viewmanager = new openerp.base.ViewManagerAction(this.session, dialog.element_id, action);
|
||||
var viewmanager = dialog.viewmanager = new openerp.base.ViewManagerAction(this, dialog.element_id, action);
|
||||
viewmanager.start();
|
||||
dialog.open();
|
||||
} else if (action.flags.new_window) {
|
||||
@@ -58,12 +70,15 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
var url = window.location.protocol + "//" + window.location.host +
|
||||
window.location.pathname + "?" + jQuery.param({ s_action : "" + key });
|
||||
window.open(url);
|
||||
if (on_closed) {
|
||||
on_closed();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (this.viewmanager) {
|
||||
this.viewmanager.stop();
|
||||
}
|
||||
this.viewmanager = new openerp.base.ViewManagerAction(this.session, this.element_id, action);
|
||||
this.viewmanager = new openerp.base.ViewManagerAction(this, this.element_id, action);
|
||||
this.viewmanager.start();
|
||||
}
|
||||
},
|
||||
@@ -81,7 +96,7 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
},
|
||||
'ir.actions.client': function (action) {
|
||||
var Handler = openerp.base.client_actions.get_object(action.tag);
|
||||
new Handler(this.session, this.element_id, action['kwargs']).start();
|
||||
new Handler(this, this.element_id, action['kwargs']).start();
|
||||
},
|
||||
close_dialog: function () {
|
||||
if (this.current_dialog) {
|
||||
@@ -91,9 +106,22 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.ActionDialog = openerp.base.Dialog.extend({
|
||||
identifier_prefix: 'action_dialog',
|
||||
stop: function() {
|
||||
this._super(this, arguments);
|
||||
if (this.close_callback) {
|
||||
this.close_callback();
|
||||
}
|
||||
if (this.viewmanager) {
|
||||
this.viewmanager.stop();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
init: function(session, element_id, dataset, views) {
|
||||
this._super(session, element_id);
|
||||
init: function(parent, element_id, dataset, views) {
|
||||
this._super(parent, element_id);
|
||||
this.model = dataset.model;
|
||||
this.dataset = dataset;
|
||||
this.searchview = null;
|
||||
@@ -140,7 +168,7 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
if (!view.controller) {
|
||||
// Lazy loading of views
|
||||
var controllerclass = this.registry.get_object(view_type);
|
||||
var controller = new controllerclass( this, this.session, this.element_id + "_view_" + view_type,
|
||||
var controller = new controllerclass( this, this.element_id + "_view_" + view_type,
|
||||
this.dataset, view.view_id, view.options);
|
||||
if (view.embedded_view) {
|
||||
controller.set_embedded_view(view.embedded_view);
|
||||
@@ -210,7 +238,7 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
if (this.searchview) {
|
||||
this.searchview.stop();
|
||||
}
|
||||
this.searchview = new openerp.base.SearchView(this, this.session, this.element_id + "_search", this.dataset, view_id, search_defaults);
|
||||
this.searchview = new openerp.base.SearchView(this, this.element_id + "_search", this.dataset, view_id, search_defaults);
|
||||
if (this.flags.search_view === false) {
|
||||
this.searchview.hide();
|
||||
}
|
||||
@@ -252,26 +280,30 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
});
|
||||
|
||||
openerp.base.NullViewManager = openerp.base.generate_null_object_class(openerp.base.ViewManager, {
|
||||
init: function() {
|
||||
this._super();
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
if(parent)
|
||||
this.session = parent.session;
|
||||
this.action = {flags: {}};
|
||||
this.sidebar = new openerp.base.NullSidebar();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO Will move to action Manager
|
||||
openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
init: function(session, element_id, action) {
|
||||
init: function(parent, element_id, action) {
|
||||
this.session = parent.session;
|
||||
var dataset;
|
||||
if (!action.res_id) {
|
||||
dataset = new openerp.base.DataSetSearch(session, action.res_model, action.context || null);
|
||||
dataset = new openerp.base.DataSetSearch(this, action.res_model, action.context || null);
|
||||
} else {
|
||||
dataset = new openerp.base.DataSetStatic(session, action.res_model, {}, [action.res_id]);
|
||||
dataset = new openerp.base.DataSetStatic(this, action.res_model, {}, [action.res_id]);
|
||||
if (action.context) {
|
||||
// TODO fme: should normalize all DataSets constructors to (session, model, context, ...)
|
||||
dataset.context = action.context;
|
||||
}
|
||||
}
|
||||
this._super(session, element_id, dataset, action.views);
|
||||
this._super(parent, element_id, dataset, action.views);
|
||||
this.action = action;
|
||||
this.flags = this.action.flags || {};
|
||||
if (action.res_model == 'board.board' && action.views.length == 1 && action.views) {
|
||||
@@ -342,19 +374,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.ActionDialog = openerp.base.Dialog.extend({
|
||||
identifier_prefix: 'action_dialog',
|
||||
stop: function() {
|
||||
this._super(this, arguments);
|
||||
if (this.close_callback) {
|
||||
this.close_callback();
|
||||
}
|
||||
if (this.viewmanager) {
|
||||
this.viewmanager.stop();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.Sidebar = openerp.base.BaseWidget.extend({
|
||||
template: "ViewManager.sidebar",
|
||||
init: function(parent, view_manager) {
|
||||
@@ -409,7 +428,6 @@ openerp.base.Sidebar = openerp.base.BaseWidget.extend({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
openerp.base.NullSidebar = openerp.base.generate_null_object_class(openerp.base.Sidebar);
|
||||
|
||||
openerp.base.Export = openerp.base.Dialog.extend({
|
||||
@@ -500,12 +518,6 @@ openerp.base.View = openerp.base.Controller.extend({
|
||||
*/
|
||||
openerp.base.views = new openerp.base.Registry();
|
||||
|
||||
openerp.base.ProcessView = openerp.base.Controller.extend({
|
||||
});
|
||||
|
||||
openerp.base.HelpView = openerp.base.Controller.extend({
|
||||
});
|
||||
|
||||
openerp.base.json_node_to_xml = function(node, single_quote, indent) {
|
||||
// For debugging purpose, this function will convert a json node back to xml
|
||||
// Maybe usefull for xml view editor
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<td><label for="db">Database:</label></td>
|
||||
<td>
|
||||
<t t-if="!db_list">
|
||||
<input type="text" name="db" value="trunk" autofocus="true"/>
|
||||
<input type="text" name="db" t-att-value="selected_db || ''" autofocus="true"/>
|
||||
</t>
|
||||
<t t-if="db_list">
|
||||
<select name="db">
|
||||
@@ -143,8 +143,8 @@
|
||||
<div class="company_logo" />
|
||||
</a>
|
||||
<h1 class="header_title" t-if="session.session_is_valid()">
|
||||
<span class="company">$company</span> - (<span class="database">$database</span>)<br/>
|
||||
<small class="username">$username session_id: <t t-esc="session.session_id"/></small>
|
||||
<span class="database"><t t-esc="session.db"/></span> - <t t-esc="session.login"/> <br/>
|
||||
<small class="username">rpc_session_id: <t t-esc="session.session_id"/></small>
|
||||
</h1>
|
||||
<div class="header_corner">
|
||||
<ul class="block" t-if="session.session_is_valid()">
|
||||
@@ -236,41 +236,40 @@
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
<table t-name="ListView">
|
||||
<table t-name="ListView" class="oe-listview-content">
|
||||
<t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/>
|
||||
<t t-set="actions_span" t-value="Math.floor((options.deletable or options.addable) ? columns_count/2 : 0)"/>
|
||||
<thead class="ui-widget-header">
|
||||
<tr>
|
||||
<th t-if="actions_span" t-att-colspan="actions_span"
|
||||
class="oe-actions">
|
||||
<t t-if="flags.action_buttons !== false">
|
||||
<button type="button" class="oe-list-add"
|
||||
t-if="options.addable">
|
||||
<t t-esc="options.addable"/>
|
||||
</button>
|
||||
<button type="button" class="oe-list-delete"
|
||||
t-if="options.selectable and options.deletable">
|
||||
Delete
|
||||
</button>
|
||||
</t>
|
||||
</th>
|
||||
<th t-att-colspan="columns_count - actions_span"
|
||||
class="oe-list-pager">
|
||||
<t t-if="flags.pager !== false">
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="first">First</button>
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="previous"
|
||||
><<</button>
|
||||
<tr t-if="flags.action_buttons !== false or flags.pager !== false">
|
||||
<th t-att-colspan="columns_count">
|
||||
<table>
|
||||
<tr>
|
||||
<td t-if="flags.action_buttons !== false" class="oe-actions">
|
||||
<button type="button" class="oe-list-add"
|
||||
t-if="options.addable">
|
||||
<t t-esc="options.addable"/>
|
||||
</button>
|
||||
<button type="button" class="oe-list-delete"
|
||||
t-if="options.selectable and options.deletable">
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
<th t-if="flags.pager !== false" class="oe-list-pager">
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="first">First</button>
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="previous"
|
||||
><</button>
|
||||
|
||||
<span class="oe-pager-state">
|
||||
</span>
|
||||
<span class="oe-pager-state">
|
||||
</span>
|
||||
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="next">>></button>
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="last">Last</button>
|
||||
</t>
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="next">></button>
|
||||
<button type="button" disabled="disabled"
|
||||
data-pager-action="last">Last</button>
|
||||
</th>
|
||||
</tr>
|
||||
</table>
|
||||
</th>
|
||||
</tr>
|
||||
<tr t-if="options.header">
|
||||
@@ -294,7 +293,7 @@
|
||||
<tr>
|
||||
<td t-if="options.selectable"/>
|
||||
<td t-foreach="aggregate_columns" t-as="column" class="oe-list-footer oe-number"
|
||||
t-att-data-field="column.field" t-att-title="column.label">
|
||||
t-att-data-field="column.id" t-att-title="column.label">
|
||||
</td>
|
||||
<td t-if="options.deletable"/>
|
||||
</tr>
|
||||
@@ -334,8 +333,8 @@
|
||||
<t t-raw="frame.render()"/>
|
||||
</t>
|
||||
<t t-name="FormView">
|
||||
<h2 class="oe_view_title"><t t-esc="view.fields_view.arch.attrs.string"/></h2>
|
||||
<div class="oe_form_header" t-att-id="view.element_id + '_header'">
|
||||
<h2 class="oe_view_title"><t t-esc="view.fields_view.arch.attrs.string"/> <button class="oe_get_xml_view">xml</button></h2>
|
||||
<div class="oe_form_buttons" t-if="view.flags.action_buttons !== false">
|
||||
<!--<button type="button" class="oe_form_button_save">
|
||||
<span class="oe_form_on_update">Save</span>
|
||||
@@ -522,7 +521,7 @@
|
||||
<img src="/base/static/src/img/icons/gtk-index.png"/></span>
|
||||
<div t-att-id="widget.cm_id" class="contextMenu" style="display:none"><ul>
|
||||
<li t-att-id="widget.cm_id + '_open'" style="color:grey">Open...</li>
|
||||
<li t-att-id="widget.cm_id + '_create'">Create and Edit...</li>
|
||||
<li t-att-id="widget.cm_id + '_create'">Create...</li>
|
||||
<li t-att-id="widget.cm_id + '_search'">Search...</li>
|
||||
</ul></div>
|
||||
</div>
|
||||
@@ -665,14 +664,28 @@
|
||||
<input type="reset" value="Clear"/>
|
||||
<button class="oe_search-view-custom-filter-btn"><span>Advanced Filter</span></button>
|
||||
<select class="oe_search-view-filters-management">
|
||||
<option value="_filters">-- Filters --</option>
|
||||
<option value="_actions">-- Actions --</option>
|
||||
<option value="save_filter">Save Filter</option>
|
||||
<option value="manage_filters">Manage Filters</option>
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
</t>
|
||||
<t t-name="SearchView.managed-filters">
|
||||
<option value="_filters">-- Filters --</option>
|
||||
<t t-set="i" t-value="0"/>
|
||||
<t t-foreach="filters" t-as="filter">
|
||||
<option t-att-value="'get:' + i"><t t-esc="filter.name"/></option>
|
||||
<t t-set="i" t-value="i+1"/>
|
||||
</t>
|
||||
<option value="_actions">-- Actions --</option>
|
||||
<option value="save_filter">Save Filter</option>
|
||||
<option value="manage_filters">Manage Filters</option>
|
||||
</t>
|
||||
<t t-name="SearchView.managed-filters.add">
|
||||
<div>
|
||||
<p>Filter Name:</p>
|
||||
<input type="text"/>
|
||||
<p>(Any existing filter with the same name will be replaced)</p>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="SearchView.render_lines">
|
||||
<table class="oe-searchview-render-line" border="0" cellspacing="0" cellpadding="0"
|
||||
t-foreach="lines" t-as="line">
|
||||
@@ -809,7 +822,7 @@
|
||||
<select class="searchview_extended_prop_op"/>
|
||||
<span class="searchview_extended_prop_value"/>
|
||||
<a class="searchview_extended_delete_prop"
|
||||
href="javascript:void(0)"><span></span></a>
|
||||
href="javascript:void(0)"><span> </span></a>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="SearchView.extended_search.proposition.char">
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
openerp.base_calendar = function(openerp) {
|
||||
QWeb.add_template('/base_calendar/static/src/xml/base_calendar.xml');
|
||||
openerp.base.views.add('calendar', 'openerp.base_calendar.CalendarView');
|
||||
openerp.base_calendar.CalendarView = openerp.base.Controller.extend({
|
||||
openerp.base_calendar.CalendarView = openerp.base.View.extend({
|
||||
// Dhtmlx scheduler ?
|
||||
init: function(view_manager, session, element_id, dataset, view_id){
|
||||
this._super(session, element_id);
|
||||
this.view_manager = view_manager;
|
||||
init: function(parent, element_id, dataset, view_id) {
|
||||
this._super(parent, element_id);
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.dataset_index = 0;
|
||||
this.model = dataset.model;
|
||||
@@ -194,7 +194,9 @@ openerp.base_calendar.CalendarView = openerp.base.Controller.extend({
|
||||
// self.color_field
|
||||
console.log('Reload Scheduler>>>')
|
||||
},
|
||||
|
||||
do_search: function (domains, contexts, groupbys) {
|
||||
this.notification.notify("Searching caldendar");
|
||||
},
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
},
|
||||
|
||||
@@ -7,11 +7,16 @@
|
||||
}
|
||||
.openerp .oe-dashboard-action {
|
||||
margin: 0 0.5em 0.5em 0;
|
||||
padding: 2px;
|
||||
}
|
||||
.openerp .oe-dashboard-action:hover {
|
||||
border: 1px dashed #ccc;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.openerp .oe-dashboard-action .oe-dashboard-action-header {
|
||||
margin: 0.3em;
|
||||
padding-bottom: 4px;
|
||||
padding-left: 0.2em
|
||||
font-size: 125%;
|
||||
font-weight: bold;
|
||||
}
|
||||
.openerp a.oe-dashboard-action-rename {
|
||||
float: left;
|
||||
@@ -42,10 +47,6 @@
|
||||
float: right;
|
||||
}
|
||||
|
||||
.openerp .oe-dashboard-action .oe-dashboard-action-content {
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
.openerp .oe-dashboard .ui-sortable-placeholder {
|
||||
border: 1px dotted black;
|
||||
visibility: visible !important;
|
||||
@@ -229,3 +230,9 @@
|
||||
color: black;
|
||||
}
|
||||
|
||||
.openerp .oe-dashboard-action .view-manager-main-content {
|
||||
padding: 2px;
|
||||
}
|
||||
.openerp .oe-dashboard-action-header .ui-icon, .openerp .oe-dashboard-action-header .oe-dashboard-action-rename {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,10 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
||||
});
|
||||
});
|
||||
|
||||
this.$element.find('a.oe-dashboard-action-rename').live('click', this.on_rename);
|
||||
//this.$element.find('a.oe-dashboard-action-rename').live('click', this.on_rename);
|
||||
this.$element.find('.oe-dashboard-action').live('mouseover mouseout', function(event) {
|
||||
$(this).find('.oe-dashboard-action-header .ui-icon, .oe-dashboard-action-header .oe-dashboard-action-rename').toggle(event.type == 'mouseover');
|
||||
});
|
||||
},
|
||||
on_undo: function() {
|
||||
this.rpc('/base/view/undo_custom', {
|
||||
@@ -70,22 +73,22 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
||||
// TODO: create a Dialog controller which optionally takes an action
|
||||
// Should set width & height automatically and take buttons & views callback
|
||||
var dialog_id = _.uniqueId('act_window_dialog');
|
||||
var action_manager = new openerp.base.ActionManager(this.session, dialog_id);
|
||||
var $dialog = $('<div id=' + dialog_id + '>').dialog({
|
||||
modal : true,
|
||||
title : 'Actions',
|
||||
width : 800,
|
||||
height : 600,
|
||||
buttons : {
|
||||
Cancel : function() {
|
||||
$(this).dialog('destroy');
|
||||
},
|
||||
Add : function() {
|
||||
self.do_add_widget(action_manager);
|
||||
$(this).dialog('destroy');
|
||||
}
|
||||
}
|
||||
});
|
||||
var action_manager = new openerp.base.ActionManager(this, dialog_id);
|
||||
$('<div id=' + dialog_id + '>').dialog({
|
||||
modal : true,
|
||||
title : 'Actions',
|
||||
width : 800,
|
||||
height : 600,
|
||||
buttons : {
|
||||
Cancel : function() {
|
||||
$(this).dialog('destroy');
|
||||
},
|
||||
Add : function() {
|
||||
self.do_add_widget(action_manager);
|
||||
$(this).dialog('destroy');
|
||||
}
|
||||
}
|
||||
});
|
||||
action_manager.start();
|
||||
action_manager.do_action(action);
|
||||
// TODO: should bind ListView#select_record in order to catch record clicking
|
||||
@@ -226,7 +229,7 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
|
||||
pager: false
|
||||
};
|
||||
new openerp.base.ActionManager(
|
||||
this.session, this.view.element_id + '_action_' + action.id)
|
||||
this, this.view.element_id + '_action_' + action.id)
|
||||
.do_action(action);
|
||||
},
|
||||
render: function() {
|
||||
@@ -280,10 +283,10 @@ if (!openerp.base_dashboard) {
|
||||
openerp.base_dashboard = {};
|
||||
}
|
||||
openerp.base_dashboard.ConfigOverview = openerp.base.View.extend({
|
||||
init: function (parent_or_session, element_id) {
|
||||
this._super(parent_or_session, element_id);
|
||||
init: function (parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.dataset = new openerp.base.DataSetSearch(
|
||||
this.session, 'ir.actions.todo');
|
||||
this, 'ir.actions.todo');
|
||||
this.dataset.domain = ['|', '&', ['type', '=', 'recurring'],
|
||||
['state', '!=', 'hidden'],
|
||||
'&', ['type', '!=', 'special'],
|
||||
@@ -344,10 +347,10 @@ openerp.base_dashboard.ConfigOverview = openerp.base.View.extend({
|
||||
openerp.base.client_actions.add(
|
||||
'board.home.applications', 'openerp.base_dashboard.ApplicationTiles');
|
||||
openerp.base_dashboard.ApplicationTiles = openerp.base.View.extend({
|
||||
init: function (parent_or_session, element_id) {
|
||||
this._super(parent_or_session, element_id);
|
||||
init: function (parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.dataset = new openerp.base.DataSetSearch(
|
||||
this.session, 'ir.ui.menu', null, [['parent_id', '=', false]]);
|
||||
this, 'ir.ui.menu', null, [['parent_id', '=', false]]);
|
||||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
@@ -374,13 +377,13 @@ openerp.base_dashboard.ApplicationTiles = openerp.base.View.extend({
|
||||
openerp.base.client_actions.add(
|
||||
'board.home.widgets', 'openerp.base_dashboard.Widgets');
|
||||
openerp.base_dashboard.Widgets = openerp.base.View.extend({
|
||||
init: function (parent_or_session, element_id) {
|
||||
this._super(parent_or_session, element_id);
|
||||
init: function (parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.user_widgets = new openerp.base.DataSetSearch(
|
||||
this.session, 'res.widget.user', null,
|
||||
['|', ['user_id', '=', false],
|
||||
['user_id', '=', parseInt(this.session.uid, 10)]]);
|
||||
this.widgets = new openerp.base.DataSetSearch(this.session, 'res.widget');
|
||||
this.widgets = new openerp.base.DataSetSearch(this, 'res.widget');
|
||||
},
|
||||
start: function () {
|
||||
this.user_widgets.read_slice(['widget_id', 'user_id'], null, null,
|
||||
|
||||
@@ -29,15 +29,15 @@
|
||||
</table>
|
||||
</t>
|
||||
<t t-name="DashBoard.action">
|
||||
<div t-att-data-id="action.attrs.name" class="oe-dashboard-action ui-widget ui-widget-content ui-helper-clearfix ui-corner-all">
|
||||
<div class="oe-dashboard-action-header ui-widget-header ui-corner-all">
|
||||
<a href="#" class="oe-dashboard-action-rename"><img src="/base/static/src/img/icons/gtk-edit.png" width="16" height="16"/></a>
|
||||
<span class="oe-dashboard-action-title"><t t-esc="action.attrs.string"/> </span>
|
||||
<div t-att-data-id="action.attrs.name" class="oe-dashboard-action">
|
||||
<h2 class="oe-dashboard-action-header oe_view_title">
|
||||
<t t-esc="action.attrs.string"/>
|
||||
<!--<a href="#" class="oe-dashboard-action-rename"><img src="/base/static/src/img/icons/gtk-edit.png" width="16" height="16"/></a>-->
|
||||
<input class="oe-dashboard-action-input" type="text" name="title" value="" style="display: none"/>
|
||||
<span class='ui-icon ui-icon-closethick'></span>
|
||||
<span class='ui-icon ui-icon-minusthick oe-dashboard-fold' t-if="!action.attrs.fold"></span>
|
||||
<span class='ui-icon ui-icon-plusthick oe-dashboard-fold' t-if="action.attrs.fold"></span>
|
||||
</div>
|
||||
</h2>
|
||||
<div t-att-id="view.element_id + '_action_' + action.attrs.name" class="oe-dashboard-action-content" t-att-style="action.attrs.fold ? 'display: none' : null"></div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -26,7 +26,7 @@ openerp.base_default_home = function (openerp) {
|
||||
openerp.base.WebClient.prototype.default_home = function () {
|
||||
var self = this;
|
||||
var Installer = new openerp.base.DataSet(
|
||||
this.session, 'base.setup.installer');
|
||||
this, 'base.setup.installer');
|
||||
Installer.call('already_installed', [], function (installed_modules) {
|
||||
if (!_(installed_modules).isEmpty()) {
|
||||
return old_home.call(self);
|
||||
|
||||
@@ -1162,7 +1162,7 @@ GanttProject.prototype.deleteChildTask = function(task)
|
||||
* @type: public
|
||||
* @topic: 1
|
||||
*/
|
||||
GanttProject.prototype.insertTask = function(id, name, EST, Duration, PercentCompleted, predecessorTaskId, parentTaskId)
|
||||
GanttProject.prototype.insertTask = function(id, name, EST, Duration, PercentCompleted, predecessorTaskId, color, parentTaskId)
|
||||
{
|
||||
var task = null;
|
||||
var _task = null;
|
||||
@@ -1205,7 +1205,7 @@ GanttProject.prototype.insertTask = function(id, name, EST, Duration, PercentCom
|
||||
return false;
|
||||
}
|
||||
|
||||
task = new GanttTaskInfo(id, name, EST, Duration, PercentCompleted, predecessorTaskId);
|
||||
task = new GanttTaskInfo(id, name, EST, Duration, PercentCompleted, predecessorTaskId, color);
|
||||
|
||||
if (!this.Chart.checkPosParentTask(parentTask, task)) {
|
||||
this.Chart.Error.throwError("DATA_INSERT_ERROR", 19, [parentTaskId,id]);
|
||||
|
||||
@@ -24,7 +24,6 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
this.date_delay = "";
|
||||
this.date_stop = "";
|
||||
this.color_field = "";
|
||||
this.day_lenth = 8;
|
||||
this.colors = [];
|
||||
this.color_values = [];
|
||||
this.calendar_fields = {};
|
||||
@@ -58,6 +57,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
this.parent = this.fields_view.arch.children[0].attrs.link;
|
||||
|
||||
this.format = "yyyy-MM-dd";
|
||||
this.grp = [];
|
||||
|
||||
self.create_gantt();
|
||||
self.get_events();
|
||||
@@ -81,7 +81,7 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
get_events: function() {
|
||||
|
||||
var self = this;
|
||||
this.dataset.read_ids(this.dataset.ids, {}, function(result) {
|
||||
this.dataset.read_slice(false, false, false, function(result) {
|
||||
self.load_event(result);
|
||||
});
|
||||
|
||||
@@ -91,7 +91,6 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
|
||||
var self = this;
|
||||
var result = events;
|
||||
var project = {};
|
||||
var smalldate = "";
|
||||
|
||||
COLOR_PALETTE = ['#ccccff', '#cc99ff', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400',
|
||||
@@ -118,13 +117,21 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
}
|
||||
}
|
||||
}
|
||||
project = new GanttProjectInfo(1, self.name, smalldate);
|
||||
ganttChartControl.addProject(project);
|
||||
if (smalldate == ""){
|
||||
smalldate = Date.today();
|
||||
}
|
||||
project = new GanttProjectInfo("_1", "", smalldate);
|
||||
ganttChartControl.addProject(project);
|
||||
}
|
||||
|
||||
//create child
|
||||
var k = 0;
|
||||
var color_box = {};
|
||||
var parents = {};
|
||||
var all_events = {};
|
||||
var child_event = {};
|
||||
var temp_id = "";
|
||||
var final_events = [];
|
||||
for (i in show_event) {
|
||||
|
||||
var res = show_event[i];
|
||||
@@ -153,8 +160,129 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
}
|
||||
if (duration == false)
|
||||
duration = 0
|
||||
task = new GanttTaskInfo(id, text, start_date, duration, 100, "", color_box[color]);
|
||||
project.addTask(task);
|
||||
|
||||
if (self.grp.length == 0){
|
||||
self.grp.push({'group_by' : this.parent})
|
||||
}
|
||||
if (self.grp != undefined){
|
||||
for (j in self.grp){
|
||||
var grp_key = res[self.grp[j]['group_by']];
|
||||
if (typeof(grp_key) == "object"){
|
||||
grp_key = res[self.grp[j]['group_by']][1];
|
||||
}
|
||||
else{
|
||||
grp_key = res[self.grp[j]['group_by']];
|
||||
}
|
||||
|
||||
if (grp_key == false){
|
||||
grp_key = "False";
|
||||
}
|
||||
|
||||
if (j == 0){
|
||||
if (parents[grp_key] == undefined){
|
||||
var mod_id = i+ "_" +j;
|
||||
parents[grp_key] = mod_id;
|
||||
child_event[mod_id] = {};
|
||||
all_events[mod_id] = {'parent': "", 'evt':[mod_id , grp_key, start_date, start_date, 100, "", "white"]};
|
||||
}
|
||||
else{
|
||||
mod_id = parents[grp_key];
|
||||
}
|
||||
temp_id = mod_id;
|
||||
}else{
|
||||
if (child_event[mod_id][grp_key] == undefined){
|
||||
var ch_mod_id = i+ "_" +j;
|
||||
child_event[mod_id][grp_key] = ch_mod_id;
|
||||
child_event[ch_mod_id] = {};
|
||||
temp_id = ch_mod_id;
|
||||
all_events[ch_mod_id] = {'parent': mod_id, 'evt':[ch_mod_id , grp_key, start_date, start_date, 100, "","white"]};
|
||||
mod_id = ch_mod_id;
|
||||
}
|
||||
else{
|
||||
mod_id = child_event[mod_id][grp_key];
|
||||
temp_id = mod_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
all_events[id] = {'parent': temp_id, 'evt':[id , text, start_date, duration, 100, "", color_box[color]]};
|
||||
final_events.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (i in final_events){
|
||||
var evt_id = final_events[i];
|
||||
var evt_date = all_events[evt_id]['evt'][2];
|
||||
while (all_events[evt_id]['parent'] != "") {
|
||||
var parent_id =all_events[evt_id]['parent'];
|
||||
if (all_events[parent_id]['evt'][2] > evt_date){
|
||||
all_events[parent_id]['evt'][2] = evt_date;
|
||||
}
|
||||
evt_id = parent_id;
|
||||
}
|
||||
}
|
||||
var evt_id = [];
|
||||
var evt_date = "";
|
||||
var evt_duration = "";
|
||||
var evt_end_date = "";
|
||||
|
||||
for (i in final_events){
|
||||
evt_id = final_events[i];
|
||||
evt_date = all_events[evt_id]['evt'][2];
|
||||
evt_duration = all_events[evt_id]['evt'][3];
|
||||
|
||||
evt_str_date = this.convert_date_str(evt_date);
|
||||
evt_end_date = this.end_date(evt_str_date, evt_duration);
|
||||
|
||||
while (all_events[evt_id]['parent'] != "") {
|
||||
var parent_id =all_events[evt_id]['parent'];
|
||||
if (all_events[parent_id]['evt'][3] < evt_end_date){
|
||||
all_events[parent_id]['evt'][3] = evt_end_date;
|
||||
}
|
||||
evt_id = parent_id;
|
||||
}
|
||||
}
|
||||
|
||||
for (j in self.grp){
|
||||
for (i in all_events){
|
||||
res = all_events[i];
|
||||
if ((typeof(res['evt'][3])) == "object"){
|
||||
res['evt'][3] = self.hours_between(res['evt'][2],res['evt'][3]);
|
||||
}
|
||||
|
||||
k = res['evt'][0].toString().indexOf('_');
|
||||
if (k != -1){
|
||||
if (res['evt'][0].substring(k) == "_"+j){
|
||||
if (j == 0){
|
||||
task = new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
project.addTask(task);
|
||||
} else {
|
||||
task = new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
prt = project.getTaskById(res['parent']);
|
||||
prt.addChildTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i in final_events){
|
||||
evt_id = final_events[i];
|
||||
res = all_events[evt_id];
|
||||
|
||||
task=new GanttTaskInfo(res['evt'][0], res['evt'][1], res['evt'][2], res['evt'][3], res['evt'][4], "",res['evt'][6]);
|
||||
prt = project.getTaskById(res['parent']);
|
||||
prt.addChildTask(task);
|
||||
}
|
||||
|
||||
oth_hgt = 264;
|
||||
min_hgt = 150;
|
||||
name_min_wdt = 150;
|
||||
gantt_hgt = jQuery(window).height() - oth_hgt;
|
||||
search_wdt = jQuery("#oe_app_search").width();
|
||||
|
||||
if (gantt_hgt > min_hgt){
|
||||
jQuery('#GanttDiv').height(gantt_hgt).width(search_wdt);
|
||||
} else{
|
||||
jQuery('#GanttDiv').height(min_hgt).width(search_wdt);
|
||||
}
|
||||
|
||||
ganttChartControl.create("GanttDiv");
|
||||
@@ -163,6 +291,69 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
ganttChartControl.attachEvent("onTaskEndDrag", function(task) {self.on_resize_drag_end(task, "drag");});
|
||||
ganttChartControl.attachEvent("onTaskDblClick", function(task) {self.open_popup(task);});
|
||||
|
||||
taskdiv = jQuery("div.taskPanel").parent();
|
||||
taskdiv.addClass('ganttTaskPanel');
|
||||
taskdiv.prev().addClass('ganttDayPanel');
|
||||
$gantt_panel = jQuery(".ganttTaskPanel , .ganttDayPanel");
|
||||
|
||||
ganttrow = jQuery('.taskPanel').closest('tr');
|
||||
gtd = ganttrow.children(':first-child');
|
||||
gtd.children().addClass('task-name');
|
||||
|
||||
jQuery(".toggle-sidebar").click(function(e) {
|
||||
self.set_width();
|
||||
});
|
||||
|
||||
jQuery(window).bind('resize',function(){
|
||||
window.clearTimeout(ganttChartControl._resize_timer);
|
||||
ganttChartControl._resize_timer = window.setTimeout(function(){
|
||||
self.reload_gantt();
|
||||
}, 200);
|
||||
});
|
||||
|
||||
jQuery("div #_1, div #_1 + div").hide();
|
||||
},
|
||||
|
||||
set_width: function() {
|
||||
|
||||
$gantt_panel.width(1);
|
||||
jQuery(".ganttTaskPanel").parent().width(1);
|
||||
|
||||
search_wdt = jQuery("#oe_app_search").width();
|
||||
day_wdt = jQuery(".ganttDayPanel").children().children().width();
|
||||
name_wdt = jQuery('.task-name').width();
|
||||
jQuery('#GanttDiv').css('width','100%');
|
||||
|
||||
if (search_wdt - day_wdt <= name_min_wdt){
|
||||
jQuery(".ganttTaskPanel").parent().width(search_wdt - name_min_wdt);
|
||||
jQuery(".ganttTaskPanel").width(search_wdt - name_min_wdt);
|
||||
jQuery(".ganttDayPanel").width(search_wdt - name_min_wdt - 14);
|
||||
jQuery('.task-name').width(name_min_wdt);
|
||||
jQuery('.task-name').children().width(name_min_wdt);
|
||||
}else{
|
||||
jQuery(".ganttTaskPanel").parent().width(day_wdt);
|
||||
jQuery(".ganttTaskPanel").width(day_wdt);
|
||||
jQuery(".taskPanel").width(day_wdt - 16);
|
||||
jQuery(".ganttDayPanel").width(day_wdt -16);
|
||||
jQuery('.task-name').width(search_wdt - day_wdt);
|
||||
jQuery('.task-name').children().width(search_wdt - day_wdt);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
end_date: function(dat, duration) {
|
||||
|
||||
var self = this;
|
||||
|
||||
dat = this.convert_str_date(dat);
|
||||
|
||||
var day = Math.floor(duration/self.day_length);
|
||||
var hrs = duration % self.day_length;
|
||||
|
||||
dat.add(day).days();
|
||||
dat.add(hrs).hour();
|
||||
|
||||
return dat;
|
||||
},
|
||||
|
||||
hours_between: function(date1, date2) {
|
||||
@@ -172,15 +363,18 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
var date2_ms = date2.getTime();
|
||||
var difference_ms = Math.abs(date1_ms - date2_ms);
|
||||
|
||||
d = Math.round(difference_ms / ONE_DAY);
|
||||
h = Math.round((difference_ms % ONE_DAY)/(1000 * 60 * 60));
|
||||
|
||||
return (d * this.day_length) + h;
|
||||
d = Math.floor(difference_ms / ONE_DAY);
|
||||
h = (difference_ms % ONE_DAY)/(1000 * 60 * 60);
|
||||
num = (d * this.day_length) + h;
|
||||
return parseFloat(num.toFixed(2));
|
||||
|
||||
},
|
||||
|
||||
open_popup : function(task) {
|
||||
var event_id = task.getId();
|
||||
|
||||
if(event_id.toString().search("_") != -1)
|
||||
return;
|
||||
if (event_id) {
|
||||
event_id = parseInt(event_id, 10);
|
||||
var dataset_event_index = jQuery.inArray(event_id, this.ids);
|
||||
@@ -214,6 +408,8 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
var event_id = task.getId();
|
||||
var data = {};
|
||||
|
||||
if(event_id.toString().search("_") != -1)
|
||||
return;
|
||||
if (evt == "drag"){
|
||||
full_date = task.getEST().set({hour: self.hh, minute : self.mm, second:0});
|
||||
data[this.date_start] = this.convert_date_str(full_date);
|
||||
@@ -272,9 +468,8 @@ init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
},
|
||||
|
||||
do_search: function (domains, contexts, groupbys) {
|
||||
|
||||
var self = this;
|
||||
|
||||
this.grp = groupbys;
|
||||
return this.rpc('/base/session/eval_domain_and_context', {
|
||||
domains: domains,
|
||||
contexts: contexts,
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
<template>
|
||||
<t t-name="GanttView">
|
||||
<h3 class="title"><t t-esc="view.fields_view.arch.attrs.string"/></h3>
|
||||
<table class="gantt-view" width="100%" height="100%" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td>
|
||||
<div style="width:100%;height:300px;position:relative" id="GanttDiv"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="padding-top:6px;position:relative" id="GanttDiv"/>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
@@ -16,9 +16,9 @@ QWeb.add_template('/base_graph/static/src/xml/base_graph.xml');
|
||||
openerp.base.views.add('graph', 'openerp.base_graph.GraphView');
|
||||
openerp.base_graph.GraphView = openerp.base.View.extend({
|
||||
|
||||
init: function(view_manager, session, element_id, dataset, view_id) {
|
||||
this._super(session, element_id);
|
||||
this.view_manager = view_manager;
|
||||
init: function(parent, element_id, dataset, view_id) {
|
||||
this._super(parent, element_id);
|
||||
this.view_manager = parent;
|
||||
this.dataset = dataset;
|
||||
this.dataset_index = 0;
|
||||
this.model = this.dataset.model;
|
||||
@@ -76,12 +76,20 @@ openerp.base_graph.GraphView = openerp.base.View.extend({
|
||||
|
||||
load_chart: function(data) {
|
||||
var self = this;
|
||||
var domain = false;
|
||||
if(data){
|
||||
this.x_title = this.all_fields[this.chart_info_fields]['string'];
|
||||
this.y_title = this.all_fields[this.operator_field]['string'];
|
||||
self.schedule_chart(data);
|
||||
}else{
|
||||
this.dataset.read_slice(this.fields, 0, false, function(res) {
|
||||
if(! _.isEmpty(this.view_manager.dataset.domain)){
|
||||
domain = this.view_manager.dataset.domain;
|
||||
}else if(! _.isEmpty(this.view_manager.action.domain)){
|
||||
domain = this.view_manager.action.domain;
|
||||
}
|
||||
this.dataset.domain = domain;
|
||||
this.dataset.context = this.view_manager.dataset.context;
|
||||
this.dataset.read_slice(_(this.fields).keys(), 0, false, function(res) {
|
||||
self.schedule_chart(res);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<template>
|
||||
<t t-name="GraphView">
|
||||
<h2 class="oe_view_title"><t t-esc="fields_view.arch.attrs.string"/></h2>
|
||||
<div t-att-id="elem_id+'-'+chart+'chart'" style="height:300px;position:relative;border:1px solid #A4BED4;"></div>
|
||||
</t>
|
||||
<div t-name="GraphView" t-att-id="elem_id+'-'+chart+'chart'"
|
||||
style="height:300px;position:relative;"/>
|
||||
</template>
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
.ui-collapsible-content-expanded {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
openerp.web_mobile.chrome_mobile = function(openerp) {
|
||||
openerp.web_mobile.Shortcuts = openerp.base.Controller.extend({
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this.rpc('/base/session/sc_list',{} ,function(res){
|
||||
self.$element.html(QWeb.render("Shortcuts", {'sc' : res}))
|
||||
self.$element.find("a").click(self.on_clicked);
|
||||
})
|
||||
},
|
||||
on_clicked: function(ev) {
|
||||
$shortcut = $(ev.currentTarget);
|
||||
id = $shortcut.data('menu');
|
||||
res_id = $shortcut.data('res');
|
||||
jQuery("#oe_header").find("h1").html($shortcut.data('name'));
|
||||
this.listview = new openerp.web_mobile.ListView(this.session, "oe_app", res_id);
|
||||
this.listview.start();
|
||||
}
|
||||
});
|
||||
openerp.web_mobile.Header = openerp.base.Controller.extend({
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
},
|
||||
start: function() {
|
||||
this.$element.html(QWeb.render("Header", this));
|
||||
this.$element.find("a").click(this.on_clicked);
|
||||
},
|
||||
on_clicked: function(ev) {
|
||||
$opt = $(ev.currentTarget);
|
||||
current_id = $opt.attr('id');
|
||||
if (current_id == 'home') {
|
||||
this.homepage = new openerp.web_mobile.Login(this.session, "oe_app");
|
||||
this.homepage.on_login_valid();
|
||||
}
|
||||
}
|
||||
});
|
||||
openerp.web_mobile.Secondary = openerp.base.Controller.extend({
|
||||
init: function(session, element_id, secondary_menu_id) {
|
||||
this._super(session, element_id);
|
||||
this.data = secondary_menu_id;
|
||||
},
|
||||
start: function(ev, id) {
|
||||
var v = { menu : this.data };
|
||||
this.$element.html(QWeb.render("Menu.secondary", v));
|
||||
this.$element.add(this.$secondary_menu).find("a").click(this.on_menu_click);
|
||||
},
|
||||
on_menu_click: function(ev, id) {
|
||||
$menu = $(ev.currentTarget);
|
||||
id = $menu.data('menu');
|
||||
for (var i = 0; i < this.data.children.length; i++) {
|
||||
if (this.data.children[i].id == id) {
|
||||
this.children = this.data.children[i];
|
||||
}
|
||||
}
|
||||
jQuery("#oe_header").find("h1").html($menu.data('name'));
|
||||
|
||||
var child_len = this.children.children.length;
|
||||
if (child_len > 0) {
|
||||
this.$element
|
||||
.removeClass("secondary_menu")
|
||||
.addClass("content_menu");
|
||||
//.hide();
|
||||
this.secondary = new openerp.web_mobile.Secondary(this.session, "oe_app", this.children);
|
||||
this.secondary.start();
|
||||
}
|
||||
else {
|
||||
if (id) {
|
||||
this.listview = new openerp.web_mobile.ListView(this.session, "oe_app", id);
|
||||
this.listview.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.web_mobile.Menu = openerp.base.Controller.extend({
|
||||
init: function(session, element_id, secondary_menu_id) {
|
||||
this._super(session, element_id);
|
||||
this.secondary_menu_id = secondary_menu_id;
|
||||
this.$secondary_menu = $("#" + secondary_menu_id);
|
||||
this.menu = false;
|
||||
},
|
||||
start: function() {
|
||||
this.rpc("/base/menu/load", {}, this.on_loaded);
|
||||
},
|
||||
on_loaded: function(data) {
|
||||
this.data = data;
|
||||
this.$element.html(QWeb.render("Menu", this.data));
|
||||
this.$element.add(this.$secondary_menu).find("a").click(this.on_menu_click);
|
||||
},
|
||||
on_menu_click: function(ev, id) {
|
||||
$menu = $(ev.currentTarget);
|
||||
id = $menu.data('menu');
|
||||
for (var i = 0; i < this.data.data.children.length; i++) {
|
||||
if (this.data.data.children[i].id == id) {
|
||||
this.children = this.data.data.children[i];
|
||||
}
|
||||
}
|
||||
jQuery("#oe_header").find("h1").html($menu.data('name'));
|
||||
this.$element
|
||||
.removeClass("login_valid")
|
||||
.addClass("secondary_menu");
|
||||
//.hide();
|
||||
this.secondary = new openerp.web_mobile.Secondary(this.session, "oe_app", this.children);
|
||||
this.secondary.start();
|
||||
}
|
||||
});
|
||||
openerp.web_mobile.Options = openerp.base.Controller.extend({
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this.$element.html(QWeb.render("Options", this));
|
||||
self.$element.find("#logout").click(self.on_logout);
|
||||
},
|
||||
on_logout: function(ev) {
|
||||
this.session.logout();
|
||||
this.login = new openerp.web_mobile.Login(this.session, "oe_app");
|
||||
this.login.start();
|
||||
}
|
||||
});
|
||||
openerp.web_mobile.Login = openerp.base.Controller.extend({
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
|
||||
jQuery("#oe_header").children().remove();
|
||||
this.rpc("/base/session/get_databases_list", {}, function(result) {
|
||||
self.db_list = result.db_list;
|
||||
self.$element.html(QWeb.render("Login", self));
|
||||
self.$element.find('#database').click(self.on_db_select);
|
||||
self.$element.find("#login").click(self.on_login);
|
||||
$.mobile.initializePage();
|
||||
})
|
||||
},
|
||||
on_db_select: function(ev) {
|
||||
var db = this.$element.find("#database option:selected").val();
|
||||
jQuery("#db_text").html(db);
|
||||
},
|
||||
on_login: function(ev) {
|
||||
ev.preventDefault();
|
||||
var self = this;
|
||||
var $e = this.$element;
|
||||
var db = $e.find("div select[name=database]").val();
|
||||
var login = $e.find("div input[name=login]").val();
|
||||
var password = $e.find("div input[name=password]").val();
|
||||
//$e.hide();
|
||||
// Should hide then call callback
|
||||
this.session.session_login(db, login, password, function() {
|
||||
if(self.session.session_is_valid()) {
|
||||
self.on_login_valid();
|
||||
} else {
|
||||
self.on_login_invalid();
|
||||
}
|
||||
});
|
||||
},
|
||||
on_login_invalid: function() {
|
||||
this.$element
|
||||
.removeClass("login_valid")
|
||||
.addClass("login_invalid")
|
||||
.show();
|
||||
},
|
||||
on_login_valid: function() {
|
||||
this.$element
|
||||
.removeClass("login_invalid")
|
||||
.addClass("login_valid");
|
||||
//.hide();
|
||||
this.$element.html(QWeb.render("HomePage", {}));
|
||||
this.header = new openerp.web_mobile.Header(this.session, "oe_header");
|
||||
this.shortcuts = new openerp.web_mobile.Shortcuts(this.session, "oe_shortcuts");
|
||||
this.menu = new openerp.web_mobile.Menu(this.session, "oe_menu", "oe_secondary_menu");
|
||||
this.options = new openerp.web_mobile.Options(this.session, "oe_options");
|
||||
this.header.start();
|
||||
this.shortcuts.start();
|
||||
this.menu.start();
|
||||
this.options.start();
|
||||
jQuery("#oe_header").find("h1").html('Home');
|
||||
|
||||
},
|
||||
do_ask_login: function(continuation) {
|
||||
this.on_login_invalid();
|
||||
this.on_login_valid.add({
|
||||
position: "last",
|
||||
unique: true,
|
||||
callback: continuation
|
||||
});
|
||||
}
|
||||
});
|
||||
openerp.web_mobile.MobileWebClient = openerp.base.Controller.extend({
|
||||
init: function(element_id) {
|
||||
var self = this;
|
||||
this._super(null, element_id);
|
||||
QWeb.add_template("xml/web_mobile.xml");
|
||||
var params = {};
|
||||
|
||||
this.$element.html(QWeb.render("WebClient", {}));
|
||||
this.session = new openerp.base.Session("oe_errors");
|
||||
this.crashmanager = new openerp.base.CrashManager(this.session);
|
||||
this.login = new openerp.web_mobile.Login(this.session, "oe_app");
|
||||
this.session.on_session_invalid.add(this.login.do_ask_login);
|
||||
},
|
||||
start: function() {
|
||||
this.session.start();
|
||||
this.login.start();
|
||||
}
|
||||
});
|
||||
openerp.web_mobile.mobilewebclient = function(element_id) {
|
||||
// TODO Helper to start mobile webclient rename it openerp.base.webclient
|
||||
var client = new openerp.web_mobile.MobileWebClient(element_id);
|
||||
client.start();
|
||||
return client;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
openerp.web_mobile.form_mobile = function (openerp) {
|
||||
openerp.web_mobile.FormView = openerp.base.Controller.extend({
|
||||
init: function(session, element_id, list_id, action) {
|
||||
this._super(session, element_id);
|
||||
this.list_id = list_id;
|
||||
this.action = action;
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
id = this.list_id;
|
||||
model = this.action.res_model;
|
||||
view_id = this.action.views[1][0];
|
||||
|
||||
this.dataset = new openerp.base.DataSetSearch(this.session, this.action.res_model, null, null);
|
||||
this.dataset.read_slice(false, false, false, function (result) {
|
||||
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
if (result[i].id == id) {
|
||||
var data = result[i];
|
||||
}
|
||||
}
|
||||
self.rpc("/base/formview/load", {"model": model, "view_id": view_id }, function (result) {
|
||||
var view_fields = result.fields_view.arch.children;
|
||||
var get_fields = self.get_fields(view_fields);
|
||||
|
||||
for (var j = 0; j < view_fields.length; j++) {
|
||||
if (view_fields[j].tag == 'notebook') {
|
||||
var notebooks = view_fields[j];
|
||||
}
|
||||
}
|
||||
$("#oe_header").find("h1").html(result.fields_view.arch.attrs.string);
|
||||
self.$element.html(QWeb.render("FormView", {'get_fields': get_fields, 'notebooks': notebooks || false, 'fields' : result.fields_view.fields, 'values' : data }));
|
||||
|
||||
self.$element.find('a').click(function(){
|
||||
|
||||
for (var k = 0; k < notebooks.children.length; k++) {
|
||||
|
||||
var text = $(this).find('.ui-btn-text').text();
|
||||
var next = $(this).next();
|
||||
var span = $(this).find('span .ui-icon');
|
||||
var content_expanded_class = "ui-collapsible-content ui-collapsible-content-expanded";
|
||||
var content_collapsed_class = "ui-collapsible-content ui-collapsible-content-collapsed";
|
||||
var expanded_class = "ui-collapsible-content-expanded";
|
||||
var collapsed_class = "ui-collapsible-content-collapsed";
|
||||
var plus_class = "ui-icon-plus";
|
||||
var minus_class = "ui-icon-minus";
|
||||
|
||||
if (notebooks.children[k].attrs.string == $.trim(text)) {
|
||||
get_fields = self.get_fields(notebooks.children[k].children);
|
||||
|
||||
$(this).parents().find('form').find('div').each( function() {
|
||||
var prev = $(this).prev();
|
||||
var trim_class = $.trim($(this).attr('class'));
|
||||
if (trim_class == content_expanded_class || trim_class == content_collapsed_class) {
|
||||
prev.removeClass('ui-btn-active');
|
||||
|
||||
if ($.trim(prev.find('.ui-btn-text').text()) != notebooks.children[k].attrs.string) {
|
||||
prev.find('span .ui-icon').removeClass(minus_class);
|
||||
prev.find('span .ui-icon').addClass(plus_class);
|
||||
$(this).removeClass(expanded_class);
|
||||
$(this).addClass(collapsed_class);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (next.hasClass(content_collapsed_class)) {
|
||||
span.removeClass(plus_class);
|
||||
span.addClass(minus_class);
|
||||
next.removeClass(collapsed_class);
|
||||
next.addClass(expanded_class);
|
||||
}
|
||||
else if (next.hasClass(content_expanded_class)) {
|
||||
span.removeClass(minus_class);
|
||||
span.addClass(plus_class);
|
||||
next.removeClass(expanded_class);
|
||||
next.addClass(collapsed_class);
|
||||
}
|
||||
if (!next.find('.detail').html().length) {
|
||||
next.find('.detail').append(QWeb.render("FormView", {'get_fields': get_fields,'fields' : result.fields_view.fields, 'values' : data }));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
get_fields: function(view_fields, fields) {
|
||||
this.fields = fields || [];
|
||||
for (var i=0; i < view_fields.length; i++){
|
||||
if (view_fields[i].tag == 'field') {
|
||||
this.fields.push(view_fields[i]);
|
||||
}
|
||||
if (view_fields[i].tag == 'group') {
|
||||
this.get_fields(view_fields[i].children, this.fields);
|
||||
}
|
||||
if (view_fields[i].tag == 'separator') {
|
||||
this.get_fields(view_fields[i].children, this.fields);
|
||||
}
|
||||
}
|
||||
return this.fields;
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
openerp.web_mobile.list_mobile = function (openerp) {
|
||||
openerp.web_mobile.ListView = openerp.base.Controller.extend({
|
||||
init: function(session, element_id, list_id) {
|
||||
this._super(session, element_id);
|
||||
this.list_id = list_id;
|
||||
},
|
||||
start: function() {
|
||||
this.rpc('/base/menu/action', {'menu_id': this.list_id},
|
||||
this.on_menu_action_loaded);
|
||||
},
|
||||
on_menu_action_loaded: function(data) {
|
||||
var self = this;
|
||||
if (data.action.length) {
|
||||
this.action = data.action[0][2];
|
||||
this.on_search_data('');
|
||||
}
|
||||
},
|
||||
on_search_data: function(request){
|
||||
if(request){
|
||||
if(request.term){
|
||||
var search_val = request.term;
|
||||
}else{
|
||||
if(request.which==27 || request.which==13 || request.which==9){
|
||||
var search_val = '';
|
||||
}else if(request.which==38 || request.which==40 || request.which==39 || request.which==37){
|
||||
return;
|
||||
}else if($("#searchid").val()==""){
|
||||
var search_val = '';
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
var search_val = '';
|
||||
}
|
||||
var self = this;
|
||||
var dataset = new openerp.base.DataSetStatic(this.session, this.action.res_model, this.action.context);
|
||||
dataset.domain=[['name','ilike',search_val]];
|
||||
dataset.name_search(search_val, dataset.domain, 'ilike',false ,function(result){
|
||||
self.$element.html(QWeb.render("ListView", {'records' : result.result}));
|
||||
self.$element.find("#searchid").focus();
|
||||
if(request.term){
|
||||
self.$element.find("#searchid").val(request.term);
|
||||
}
|
||||
self.$element.find("#searchid").autocomplete({
|
||||
source: function(req) { self.on_search_data(req); },
|
||||
focus: function(e, ui) {
|
||||
e.preventDefault();
|
||||
},
|
||||
html: true,
|
||||
minLength: 0,
|
||||
delay: 0
|
||||
});
|
||||
self.$element.find("#searchid").keyup(self.on_search_data);
|
||||
self.$element.find("a#list-id").click(self.on_list_click);
|
||||
});
|
||||
},
|
||||
on_list_click: function(ev) {
|
||||
$record = $(ev.currentTarget);
|
||||
var self = this;
|
||||
id = $record.data('id');
|
||||
this.formview = new openerp.web_mobile.FormView(this.session, "oe_app", id, this.action);
|
||||
this.formview.start();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,257 +1,5 @@
|
||||
|
||||
openerp.web_mobile = function(openerp) {
|
||||
|
||||
openerp.web_mobile = {};
|
||||
|
||||
openerp.web_mobile.MobileWebClient = openerp.base.Controller.extend({
|
||||
init: function(element_id) {
|
||||
var self = this;
|
||||
this._super(null, element_id);
|
||||
QWeb.add_template("xml/web_mobile.xml");
|
||||
var params = {};
|
||||
|
||||
this.$element.html(QWeb.render("WebClient", {}));
|
||||
this.session = new openerp.base.Session("oe_errors");
|
||||
this.crashmanager = new openerp.base.CrashManager(this.session);
|
||||
this.login = new openerp.web_mobile.Login(this.session, "oe_app");
|
||||
|
||||
this.session.on_session_invalid.add(this.login.do_ask_login);
|
||||
|
||||
},
|
||||
start: function() {
|
||||
this.session.start();
|
||||
this.login.start();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.web_mobile.mobilewebclient = function(element_id) {
|
||||
// TODO Helper to start mobile webclient rename it openerp.base.webclient
|
||||
var client = new openerp.web_mobile.MobileWebClient(element_id);
|
||||
client.start();
|
||||
return client;
|
||||
};
|
||||
|
||||
openerp.web_mobile.Header = openerp.base.Controller.extend({
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
},
|
||||
start: function() {
|
||||
this.$element.html(QWeb.render("Header", this));
|
||||
this.$element.find("a").click(this.on_clicked);
|
||||
},
|
||||
on_clicked: function(ev) {
|
||||
$opt = $(ev.currentTarget);
|
||||
current_id = $opt.attr('id');
|
||||
if (current_id == 'home') {
|
||||
this.homepage = new openerp.web_mobile.Login(this.session, "oe_app");
|
||||
this.homepage.on_login_valid();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
openerp.web_mobile.Shortcuts = openerp.base.Controller.extend({
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this.rpc('/base/session/sc_list',{} ,function(res){
|
||||
self.$element.html(QWeb.render("Shortcuts", {'sc' : res}))
|
||||
self.$element.find("a").click(self.on_clicked);
|
||||
})
|
||||
},
|
||||
on_clicked: function(ev) {
|
||||
$shortcut = $(ev.currentTarget);
|
||||
id = $shortcut.data('menu');
|
||||
res_id = $shortcut.data('res');
|
||||
jQuery("#oe_header").find("h1").html($shortcut.data('name'));
|
||||
this.listview = new openerp.web_mobile.ListView(this.session, "oe_app", res_id);
|
||||
this.listview.start();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.web_mobile.ListView = openerp.base.Controller.extend({
|
||||
init: function(session, element_id, list_id) {
|
||||
this._super(session, element_id);
|
||||
this.list_id = list_id;
|
||||
},
|
||||
start: function() {
|
||||
this.rpc('/base/menu/action', {'menu_id': this.list_id},
|
||||
this.on_menu_action_loaded);
|
||||
},
|
||||
on_menu_action_loaded: function(data) {
|
||||
var self = this;
|
||||
if (data.action.length) {
|
||||
var action = data.action[0][2];
|
||||
self.on_action(action);
|
||||
}
|
||||
},
|
||||
on_action: function(action) {
|
||||
var self = this;
|
||||
var view_id = action.views[0][0];
|
||||
(new openerp.base.DataSetSearch(this.session, action.res_model, null, null))
|
||||
.read_slice(false, false, false, function(result){
|
||||
this.listview = new openerp.web_mobile.ListView(this.session, "oe_app");
|
||||
self.$element.html(QWeb.render("ListView", {'records' : result}));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
openerp.web_mobile.Secondary = openerp.base.Controller.extend({
|
||||
init: function(session, element_id, secondary_menu_id) {
|
||||
this._super(session, element_id);
|
||||
this.data = secondary_menu_id;
|
||||
},
|
||||
start: function(ev, id) {
|
||||
var v = { menu : this.data };
|
||||
this.$element.html(QWeb.render("Menu.secondary", v));
|
||||
this.$element.add(this.$secondary_menu).find("a").click(this.on_menu_click);
|
||||
},
|
||||
on_menu_click: function(ev, id) {
|
||||
$menu = $(ev.currentTarget);
|
||||
id = $menu.data('menu');
|
||||
for (var i = 0; i < this.data.children.length; i++) {
|
||||
if (this.data.children[i].id == id) {
|
||||
this.children = this.data.children[i];
|
||||
}
|
||||
}
|
||||
jQuery("#oe_header").find("h1").html($menu.data('name'));
|
||||
|
||||
var child_len = this.children.children.length;
|
||||
if (child_len > 0) {
|
||||
this.$element
|
||||
.removeClass("secondary_menu")
|
||||
.addClass("content_menu");
|
||||
//.hide();
|
||||
this.secondary = new openerp.web_mobile.Secondary(this.session, "oe_app", this.children);
|
||||
this.secondary.start();
|
||||
}
|
||||
else {
|
||||
if (id) {
|
||||
this.listview = new openerp.web_mobile.ListView(this.session, "oe_app", id);
|
||||
this.listview.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.web_mobile.Menu = openerp.base.Controller.extend({
|
||||
init: function(session, element_id, secondary_menu_id) {
|
||||
this._super(session, element_id);
|
||||
this.secondary_menu_id = secondary_menu_id;
|
||||
this.$secondary_menu = $("#" + secondary_menu_id);
|
||||
this.menu = false;
|
||||
},
|
||||
start: function() {
|
||||
this.rpc("/base/menu/load", {}, this.on_loaded);
|
||||
},
|
||||
on_loaded: function(data) {
|
||||
this.data = data;
|
||||
this.$element.html(QWeb.render("Menu", this.data));
|
||||
this.$element.add(this.$secondary_menu).find("a").click(this.on_menu_click);
|
||||
},
|
||||
on_menu_click: function(ev, id) {
|
||||
$menu = $(ev.currentTarget);
|
||||
id = $menu.data('menu');
|
||||
for (var i = 0; i < this.data.data.children.length; i++) {
|
||||
if (this.data.data.children[i].id == id) {
|
||||
this.children = this.data.data.children[i];
|
||||
}
|
||||
}
|
||||
jQuery("#oe_header").find("h1").html($menu.data('name'));
|
||||
this.$element
|
||||
.removeClass("login_valid")
|
||||
.addClass("secondary_menu");
|
||||
//.hide();
|
||||
this.secondary = new openerp.web_mobile.Secondary(this.session, "oe_app", this.children);
|
||||
this.secondary.start();
|
||||
}
|
||||
});
|
||||
|
||||
openerp.web_mobile.Options = openerp.base.Controller.extend({
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this.$element.html(QWeb.render("Options", this));
|
||||
self.$element.find("#logout").click(self.on_logout);
|
||||
},
|
||||
on_logout: function(ev) {
|
||||
this.session.logout();
|
||||
this.login = new openerp.web_mobile.Login(this.session, "oe_app");
|
||||
this.login.start();
|
||||
}
|
||||
});
|
||||
openerp.web_mobile.Login = openerp.base.Controller.extend({
|
||||
init: function(session, element_id) {
|
||||
this._super(session, element_id);
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
|
||||
jQuery("#oe_header").children().remove();
|
||||
this.rpc("/base/session/get_databases_list", {}, function(result) {
|
||||
self.db_list = result.db_list;
|
||||
self.$element.html(QWeb.render("Login", self));
|
||||
self.$element.find('#database').click(self.on_db_select);
|
||||
self.$element.find("#login").click(self.on_login);
|
||||
$.mobile.initializePage();
|
||||
})
|
||||
},
|
||||
on_db_select: function(ev) {
|
||||
var db = this.$element.find("#database option:selected").val();
|
||||
jQuery("#db_text").html(db);
|
||||
},
|
||||
on_login: function(ev) {
|
||||
ev.preventDefault();
|
||||
var self = this;
|
||||
var $e = this.$element;
|
||||
var db = $e.find("div select[name=database]").val();
|
||||
var login = $e.find("div input[name=login]").val();
|
||||
var password = $e.find("div input[name=password]").val();
|
||||
//$e.hide();
|
||||
// Should hide then call callback
|
||||
this.session.session_login(db, login, password, function() {
|
||||
if(self.session.session_is_valid()) {
|
||||
self.on_login_valid();
|
||||
} else {
|
||||
self.on_login_invalid();
|
||||
}
|
||||
});
|
||||
},
|
||||
on_login_invalid: function() {
|
||||
this.$element
|
||||
.removeClass("login_valid")
|
||||
.addClass("login_invalid")
|
||||
.show();
|
||||
},
|
||||
on_login_valid: function() {
|
||||
this.$element
|
||||
.removeClass("login_invalid")
|
||||
.addClass("login_valid");
|
||||
//.hide();
|
||||
this.$element.html(QWeb.render("HomePage", {}));
|
||||
this.header = new openerp.web_mobile.Header(this.session, "oe_header");
|
||||
this.shortcuts = new openerp.web_mobile.Shortcuts(this.session, "oe_shortcuts");
|
||||
this.menu = new openerp.web_mobile.Menu(this.session, "oe_menu", "oe_secondary_menu");
|
||||
this.options = new openerp.web_mobile.Options(this.session, "oe_options");
|
||||
this.header.start();
|
||||
this.shortcuts.start();
|
||||
this.menu.start();
|
||||
this.options.start();
|
||||
jQuery("#oe_header").find("h1").html('Home');
|
||||
|
||||
},
|
||||
do_ask_login: function(continuation) {
|
||||
this.on_login_invalid();
|
||||
this.on_login_valid.add({
|
||||
position: "last",
|
||||
unique: true,
|
||||
callback: continuation
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
openerp.web_mobile = function(instance) {
|
||||
openerp.web_mobile.chrome_mobile(instance);
|
||||
openerp.web_mobile.list_mobile(instance);
|
||||
openerp.web_mobile.form_mobile(instance);
|
||||
};
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
<html style="height: 100%">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Login Page OpenERP mobile</title>
|
||||
<title>OpenERP Web Mobile</title>
|
||||
<link rel="stylesheet" href="/web_mobile/static/lib/jquery_mobile/css/jquery.mobile-1.0a4.1.css" />
|
||||
|
||||
<script type="text/javascript" src="/base/static/lib/LABjs/LAB.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/LABjs/LAB.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/jquery/jquery-1.6.2.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/jquery.ui/js/jquery-ui-1.8.9.custom.min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web_mobile/static/lib/jquery_mobile/js/jquery.mobile-1.0a4.1.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script>
|
||||
<script type="text/javascript" src="/base/static/lib/underscore/underscore.js"></script>
|
||||
@@ -17,21 +19,23 @@
|
||||
<script type="text/javascript" src="/base/static/src/js/base.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/chrome.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/data.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/dates.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/dates.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/web_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/web_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/chrome_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/list_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web_mobile/static/src/js/form_mobile.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="/web_mobile/static/src/css/web_mobile.css"/>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
QWeb = window.QWeb || new QWeb2.Engine();
|
||||
var oe = openerp.init();
|
||||
openerp.web_mobile(oe);
|
||||
oe.web_mobile.mobilewebclient("moe");
|
||||
$("html").page();
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="moe" class="openerp" data-role="page"></div>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<span id="db_text" class="ui-btn-text">Choose Database...</span>
|
||||
<span class="ui-icon ui-icon-arrow-d ui-icon-shadow"></span>
|
||||
</span>
|
||||
<select data-native-menu="false" id="database" name="database" tabindex="-1">
|
||||
<select id="database" name="database">
|
||||
<t t-foreach="db_list" t-as="opt">
|
||||
<option t-att-value="opt"><t t-esc="opt"/></option>
|
||||
</t>
|
||||
@@ -67,12 +67,17 @@
|
||||
|
||||
<t t-name="ListView">
|
||||
<div role="main" class="ui-content" data-role="content">
|
||||
<ul data-role="listview" class="ui-listview">
|
||||
<form class="ui-listview-filter ui-bar-c" role="search">
|
||||
<div id="search-data" class="ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-searchfield ui-body-c">
|
||||
<input id="searchid" placeholder="Filter items..." data-type="search" class="ui-input-text ui-body-null" autosearch="true" setTimeDefault="700"/>
|
||||
</div>
|
||||
</form>
|
||||
<ul role="listbox" data-role="listview" class="ui-listview">
|
||||
<li data-theme="c" class="ui-btn ui-btn-icon-right ui-li ui-btn-up-c" t-foreach="records" t-as="record">
|
||||
<div class="ui-btn-inner ui-li">
|
||||
<div class="ui-btn-text">
|
||||
<a href="#" class="ui-link-inherit">
|
||||
<span><t t-esc="record.name"/></span>
|
||||
<a id="list-id" t-att-data-id="record[0]" href="#" class="ui-link-inherit">
|
||||
<span><t t-esc="record[1]"/></span>
|
||||
</a>
|
||||
</div>
|
||||
<span class="ui-icon ui-icon-arrow-r"></span>
|
||||
@@ -82,6 +87,151 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="FormView">
|
||||
<div role="main" class="ui-content" data-role="content">
|
||||
<form>
|
||||
<t t-foreach="get_fields" t-as="field">
|
||||
<div data-role="fieldcontain">
|
||||
|
||||
<label class="ui-input-text">
|
||||
<span>
|
||||
<t t-if="!(field.attrs.string)" t-esc="fields[field.attrs.name].string"></t>
|
||||
<t t-if="field.attrs.string" t-esc="field.attrs.string"></t>
|
||||
</span>:
|
||||
</label>
|
||||
<t t-if="fields[field.attrs.name].type == 'char'">
|
||||
<t t-if="values[field.attrs.name]">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" t-att-value="values[field.attrs.name]"/><br/>
|
||||
</t>
|
||||
<t t-if="!(values[field.attrs.name])">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" value=""/><br/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="fields[field.attrs.name].type == 'boolean'">
|
||||
<t t-if="values[field.attrs.name]">
|
||||
<input type="checkbox" checked="yes"/><br/>
|
||||
</t>
|
||||
<t t-if="!(values[field.attrs.name])">
|
||||
<input type="checkbox"/><br/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="fields[field.attrs.name].type == 'text'">
|
||||
<input type="text" style="width: 100%"/><br/>
|
||||
</t>
|
||||
<t t-if="fields[field.attrs.name].type == 'selection'">
|
||||
<div class="ui-select">
|
||||
<div data-theme="c" class="ui-btn ui-btn-icon-right ui-btn-corner-all ui-shadow ui-btn-up-c">
|
||||
<span class="ui-btn-inner ui-btn-corner-all">
|
||||
<span class="ui-btn-text">
|
||||
<t t-if="values[field.attrs.name]">
|
||||
<t t-foreach="fields[field.attrs.name].selection" t-as="opt">
|
||||
<t t-if="opt[0] == (values[field.attrs.name])">
|
||||
<t t-esc="opt[1]"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</span>
|
||||
<span class="ui-icon ui-icon-arrow-d ui-icon-shadow"></span>
|
||||
</span>
|
||||
<select>
|
||||
<t t-foreach="fields[field.attrs.name].selection" t-as="opt">
|
||||
<option t-att-value="opt[0]"><t t-esc="opt[1]"/></option>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="fields[field.attrs.name].type == 'many2one'">
|
||||
<div class="ui-select">
|
||||
<div data-theme="c" class="ui-btn ui-btn-icon-right ui-btn-corner-all ui-shadow ui-btn-up-c">
|
||||
<span class="ui-btn-inner ui-btn-corner-all">
|
||||
<span class="ui-btn-text">
|
||||
<t t-esc="values[field.attrs.name][1]"/>
|
||||
</span>
|
||||
<span class="ui-icon ui-icon-arrow-d ui-icon-shadow"></span>
|
||||
</span>
|
||||
<select>
|
||||
<t t-if="fields[field.attrs.name].selection">
|
||||
<t t-foreach="fields[field.attrs.name].selection" t-as="opt">
|
||||
<option t-att-value="opt[0]"><t t-esc="opt[1]"/></option>
|
||||
</t>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="fields[field.attrs.name].type == 'one2many'">
|
||||
<t t-if="values[field.attrs.name]">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" t-att-value="values[field.attrs.name]"/><br/>
|
||||
</t>
|
||||
<t t-if="!(values[field.attrs.name])">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" value=""/><br/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="fields[field.attrs.name].type == 'many2many'">
|
||||
<t t-if="values[field.attrs.name]">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" t-att-value="values[field.attrs.name]"/><br/>
|
||||
</t>
|
||||
<t t-if="!(values[field.attrs.name])">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" value=""/><br/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="fields[field.attrs.name].type == 'float'">
|
||||
<t t-if="values[field.attrs.name]">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" t-att-value="values[field.attrs.name]"/><br/>
|
||||
</t>
|
||||
<t t-if="!(values[field.attrs.name])">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" value=""/><br/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="fields[field.attrs.name].type == 'date'">
|
||||
<t t-if="values[field.attrs.name]">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" t-att-value="values[field.attrs.name]"/><br/>
|
||||
</t>
|
||||
<t t-if="!(values[field.attrs.name])">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" value=""/><br/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="fields[field.attrs.name].type == 'datetime'">
|
||||
<t t-if="values[field.attrs.name]">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" t-att-value="values[field.attrs.name]"/><br/>
|
||||
</t>
|
||||
<t t-if="!(values[field.attrs.name])">
|
||||
<input class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c" type="text" value=""/><br/>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="notebooks">
|
||||
<t t-foreach="notebooks.children" t-as="page">
|
||||
<div class="info ui-collapsible-contain" data-collapsed="true" data-role="collapsible">
|
||||
<h1 class="ui-collapsible-heading">
|
||||
<a class="ui-collapsible-heading-toggle ui-btn ui-btn-icon-left ui-shadow ui-corner-all ui-btn-up-c" href="#" data-theme="c" t-id="page.attrs.string">
|
||||
<span class="ui-btn-inner ui-corner-all">
|
||||
<span class="ui-btn-text">
|
||||
<t t-esc="page.attrs.string"></t>
|
||||
<!-- <span class="ui-collapsible-heading-status"></span> -->
|
||||
</span>
|
||||
<span data-theme="d" class="ui-btn ui-btn-icon-left ui-btn-corner-all ui-shadow ui-btn-up-d">
|
||||
<span class="ui-btn-inner ui-btn-corner-all ui-corner-all">
|
||||
<span class="ui-btn-text"></span>
|
||||
<span class="ui-icon ui-icon-shadow ui-icon-plus"></span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
<div class="ui-collapsible-content ui-collapsible-content-collapsed" aria-hidden="true">
|
||||
<div class="detail"></div>
|
||||
</div>
|
||||
</h1>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</form>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
<t t-name="Shortcuts">
|
||||
<ul data-dividertheme="b" data-theme="c" data-inset="true" data-role="listview" class="ui-listview ui-listview-inset ui-corner-all ui-shadow">
|
||||
<li data-role="list-divider" role="heading" class="ui-li ui-li-divider ui-btn ui-bar-b ui-corner-top ui-btn-up-undefined">
|
||||
|
||||
@@ -172,9 +172,8 @@ class Context(BaseContext):
|
||||
ctx = self.session.evaluation_context(context)
|
||||
if self.own:
|
||||
ctx.update(self.own)
|
||||
return eval(self.get_context_string(),
|
||||
SuperDict(ctx))
|
||||
|
||||
return eval(self.get_context_string(), SuperDict(ctx))
|
||||
|
||||
class SuperDict(dict):
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
@@ -182,7 +181,7 @@ class SuperDict(dict):
|
||||
except KeyError:
|
||||
raise AttributeError(name)
|
||||
def __getitem__(self, key):
|
||||
tmp = super(type(self), self).__getitem__(key)
|
||||
tmp = super(SuperDict, self).__getitem__(key)
|
||||
if isinstance(tmp, dict):
|
||||
return SuperDict(tmp)
|
||||
return tmp
|
||||
@@ -208,8 +207,7 @@ class CompoundDomain(BaseDomain):
|
||||
|
||||
ctx = dict(context or {})
|
||||
ctx.update(self.get_eval_context() or {})
|
||||
ctx['context'] = ctx
|
||||
|
||||
|
||||
domain.session = self.session
|
||||
final_domain.extend(domain.evaluate(ctx))
|
||||
return final_domain
|
||||
@@ -247,8 +245,7 @@ class CompoundContext(BaseContext):
|
||||
continue
|
||||
|
||||
ctx.update(final_context)
|
||||
ctx["context"] = ctx
|
||||
|
||||
|
||||
context_to_eval.session = self.session
|
||||
final_context.update(context_to_eval.evaluate(ctx))
|
||||
return final_context
|
||||
|
||||
@@ -179,10 +179,10 @@ class OpenERPSession(object):
|
||||
:returns: the augmented context
|
||||
:rtype: dict
|
||||
"""
|
||||
d = {}
|
||||
d.update(self.base_eval_context)
|
||||
d = dict(self.base_eval_context)
|
||||
if context:
|
||||
d.update(context)
|
||||
d['context'] = d
|
||||
return d
|
||||
|
||||
def eval_context(self, context_to_eval, context=None):
|
||||
@@ -202,7 +202,6 @@ class OpenERPSession(object):
|
||||
ctx = dict(
|
||||
self.base_eval_context,
|
||||
**(context or {}))
|
||||
ctx['context'] = ctx
|
||||
|
||||
# adding the context of the session to send to the openerp server
|
||||
ccontext = nonliterals.CompoundContext(self.context, context_to_eval or {})
|
||||
@@ -227,12 +226,9 @@ class OpenERPSession(object):
|
||||
if isinstance(domain, list):
|
||||
return domain
|
||||
|
||||
ctx = dict(context or {})
|
||||
ctx['context'] = ctx
|
||||
|
||||
cdomain = nonliterals.CompoundDomain(domain)
|
||||
cdomain.session = self
|
||||
return cdomain.evaluate(ctx)
|
||||
return cdomain.evaluate(context or {})
|
||||
|
||||
#----------------------------------------------------------
|
||||
# OpenERP Web RequestHandler
|
||||
@@ -416,7 +412,7 @@ class Root(object):
|
||||
if path_addons not in sys.path:
|
||||
sys.path.insert(0, path_addons)
|
||||
for i in os.listdir(path_addons):
|
||||
if i not in sys.modules:
|
||||
if i not in addons_module:
|
||||
manifest_path = os.path.join(path_addons, i, '__openerp__.py')
|
||||
if os.path.isfile(manifest_path):
|
||||
manifest = eval(open(manifest_path).read())
|
||||
@@ -454,7 +450,7 @@ class Root(object):
|
||||
#for the mobile web client we are supposed to use a different url to just add '/mobile'
|
||||
raise cherrypy.HTTPRedirect('/web_mobile/static/src/web_mobile.html', 301)
|
||||
else:
|
||||
raise cherrypy.HTTPRedirect('/base/static/src/base.html', 301)
|
||||
raise cherrypy.HTTPRedirect('/base/webclient/home', 301)
|
||||
default.exposed = True
|
||||
|
||||
def main(argv):
|
||||
|
||||
Reference in New Issue
Block a user