[Merge] Merged with main branch.
bzr revid: noz@tinyerp.com-20110727053822-olbfv0ljww17cz9c
This commit is contained in:
@@ -3,4 +3,37 @@
|
||||
"version" : "2.0",
|
||||
"depends" : [],
|
||||
'active': True,
|
||||
'js' : [
|
||||
"static/lib/datejs/date-en-US.js",
|
||||
"static/lib/jquery/jquery-1.5.2.js",
|
||||
"static/lib/jquery.validate/jquery.validate.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",
|
||||
],
|
||||
}
|
||||
|
||||
+127
-56
@@ -56,6 +56,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"
|
||||
|
||||
@@ -170,37 +263,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)
|
||||
@@ -226,31 +288,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,
|
||||
@@ -829,6 +872,34 @@ class SearchView(View):
|
||||
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,56 +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.5.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/controller.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/search.js"></script>
|
||||
<script type="text/javascript" src="/base/static/src/js/view_tree.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>
|
||||
@@ -1093,6 +1093,10 @@ background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */
|
||||
.openerp .closed-sidebar .toggle-sidebar {
|
||||
border-left: none;
|
||||
}
|
||||
.openerp li.oe_sidebar_print {
|
||||
padding-left: 20px;
|
||||
background: 1px 3px url(../img/icons/gtk-print.png) no-repeat;
|
||||
}
|
||||
|
||||
.openerp.kitten-mode-activated .main_table {
|
||||
background: url(http://placekitten.com/g/1500/800) repeat;
|
||||
|
||||
+146
-164
@@ -137,63 +137,116 @@ openerp.base.Registry = openerp.base.Class.extend( /** @lends openerp.base.Regis
|
||||
});
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* OpenERP session aware controller
|
||||
* a controller takes an already existing dom element and manage it
|
||||
*/
|
||||
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() {};
|
||||
}
|
||||
}
|
||||
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({
|
||||
openerp.base.Controller = openerp.base.Controller.extend( /** @lends openerp.base.Controller# */{
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.$element.notify({
|
||||
speed: 500,
|
||||
expires: 1500
|
||||
});
|
||||
if(this.controller_parent && this.controller_parent.session) {
|
||||
this.session = this.controller_parent.session;
|
||||
}
|
||||
},
|
||||
notify: function(title, text) {
|
||||
this.$element.notify('create', {
|
||||
title: title,
|
||||
text: text
|
||||
});
|
||||
/**
|
||||
* 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) {
|
||||
return this.session.rpc(url, data, success, error);
|
||||
},
|
||||
warn: function(title, text) {
|
||||
this.$element.notify('create', 'oe_notification_alert', {
|
||||
title: title,
|
||||
text: text
|
||||
});
|
||||
do_action: function(action, on_finished) {
|
||||
return this.parent.do_action(action, on_finished);
|
||||
}
|
||||
});
|
||||
|
||||
// Session should be a Class not Controller
|
||||
openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.base.Session# */{
|
||||
/**
|
||||
* 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.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();
|
||||
}
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
||||
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(parent, element_id, server, port) {
|
||||
this._super(element_id);
|
||||
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";
|
||||
@@ -372,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;
|
||||
@@ -388,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(';');
|
||||
@@ -399,15 +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',
|
||||
@@ -415,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++) {
|
||||
@@ -441,108 +506,25 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* OpenERP session aware controller
|
||||
* a controller takes an already existing dom element and manage it
|
||||
*/
|
||||
openerp.base.Controller = openerp.base.BasicController.extend( /** @lends openerp.base.Controller# */{
|
||||
/**
|
||||
* @constructs
|
||||
* @extends openerp.base.BasicController
|
||||
*/
|
||||
openerp.base.Notification = openerp.base.Controller.extend({
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
if(this.parent && this.parent.session) {
|
||||
this.session = this.parent.session;
|
||||
}
|
||||
this.$element.notify({
|
||||
speed: 500,
|
||||
expires: 1500
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 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) {
|
||||
return this.session.rpc(url, data, success, error);
|
||||
notify: function(title, text) {
|
||||
this.$element.notify('create', {
|
||||
title: title,
|
||||
text: text
|
||||
});
|
||||
},
|
||||
do_action: function(action, on_finished) {
|
||||
return this.parent.do_action(action, on_finished);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 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 a 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) {
|
||||
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;
|
||||
},
|
||||
/**
|
||||
* "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();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 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
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -550,6 +532,7 @@ openerp.base.Dialog = openerp.base.BaseWidget.extend({
|
||||
dialog_title: "",
|
||||
identifier_prefix: 'dialog',
|
||||
init: function (parent, options) {
|
||||
var self = this;
|
||||
this._super(parent);
|
||||
this.options = {
|
||||
modal: true,
|
||||
@@ -560,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_') {
|
||||
@@ -623,11 +609,7 @@ 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');
|
||||
}
|
||||
});
|
||||
@@ -1132,7 +1114,7 @@ openerp.base.WebClient = openerp.base.Controller.extend({
|
||||
init: function(element_id) {
|
||||
this._super(null, element_id);
|
||||
|
||||
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) {
|
||||
this.$element.addClass("kitten-mode-activated");
|
||||
@@ -1144,7 +1126,7 @@ openerp.base.WebClient = openerp.base.Controller.extend({
|
||||
this.crashmanager = new openerp.base.CrashManager(this);
|
||||
this.crashmanager.start(false);
|
||||
|
||||
// Do you autorize this ?
|
||||
// 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, "oe_header");
|
||||
|
||||
@@ -66,7 +66,7 @@ openerp.base.controller = function(instance) {
|
||||
|
||||
return Class;
|
||||
};
|
||||
})(instance.base);
|
||||
})();
|
||||
|
||||
// todo change john resig class to keep window clean
|
||||
instance.base.Class = window.Class
|
||||
@@ -121,14 +121,39 @@ instance.base.callback = function(obj, method) {
|
||||
};
|
||||
|
||||
/**
|
||||
* OpenERP Controller
|
||||
* 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.BasicController = instance.base.Class.extend( /** @lends instance.base.BasicController# */{
|
||||
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 event can be hooked in between.
|
||||
*
|
||||
* @constructs
|
||||
* start() instead of init so that events can be hooked in between.
|
||||
*/
|
||||
init: function(parent, element_id) {
|
||||
this.element_id = element_id;
|
||||
@@ -137,12 +162,14 @@ instance.base.BasicController = instance.base.Class.extend( /** @lends instance.
|
||||
instance.screen[element_id] = this;
|
||||
}
|
||||
// save the parent children relationship
|
||||
this.controller_parent = null;
|
||||
this.controller_parent = parent;
|
||||
this.controller_children = [];
|
||||
this.parent = parent;
|
||||
if(this.parent && this.parent.children) {
|
||||
this.parent.children.push(this);
|
||||
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) {
|
||||
@@ -156,9 +183,8 @@ instance.base.BasicController = instance.base.Class.extend( /** @lends instance.
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Controller start
|
||||
* event binding, rpc and callback calling required to initialize the
|
||||
* object can happen here
|
||||
* 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
|
||||
@@ -174,6 +200,12 @@ instance.base.BasicController = instance.base.Class.extend( /** @lends instance.
|
||||
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);
|
||||
|
||||
@@ -240,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(parent, model, context) {
|
||||
this._super(parent);
|
||||
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;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
openerp.base.form = function (openerp) {
|
||||
|
||||
openerp.base.views.add('form', 'openerp.base.FormView');
|
||||
openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormView# */{
|
||||
openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormView# */{
|
||||
/**
|
||||
* Indicates that this view is not searchable, and thus that no search
|
||||
* view should be displayed (if there is one active).
|
||||
@@ -19,6 +19,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
*/
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.set_default_options();
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
@@ -53,10 +54,14 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
context.add(this.view_manager.action.context);
|
||||
}
|
||||
return this.rpc("/base/formview/load", {"model": this.model, "view_id": this.view_id,
|
||||
toolbar:!!this.flags.sidebar, context: context}, this.on_loaded);
|
||||
toolbar: this.options.sidebar, context: context}, this.on_loaded);
|
||||
}
|
||||
},
|
||||
stop: function() {
|
||||
if (this.sidebar) {
|
||||
this.sidebar.attachments.stop();
|
||||
this.sidebar.stop();
|
||||
}
|
||||
_.each(this.widgets, function(w) {
|
||||
w.stop();
|
||||
});
|
||||
@@ -85,12 +90,16 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
$('<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);
|
||||
if (this.options.sidebar && this.options.sidebar_id) {
|
||||
this.sidebar = new openerp.base.Sidebar(this, this.options.sidebar_id);
|
||||
this.sidebar.start();
|
||||
this.sidebar.attachments = new openerp.base.form.SidebarAttachments(this.sidebar, this.sidebar.add_section("Attachments"), this);
|
||||
this.sidebar.add_toolbar(data.fields_view.toolbar);
|
||||
this.sidebar.do_unfold();
|
||||
}
|
||||
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
|
||||
@@ -98,13 +107,17 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
} else {
|
||||
promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded);
|
||||
}
|
||||
self.$element.show();
|
||||
if(this.view_manager.sidebar)
|
||||
this.view_manager.sidebar.do_refresh(true);
|
||||
this.$element.show();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.$element.show();
|
||||
}
|
||||
return promise;
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.$element.hide();
|
||||
}
|
||||
},
|
||||
on_record_loaded: function(record) {
|
||||
if (!record) {
|
||||
@@ -144,7 +157,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.on_form_changed();
|
||||
this.show_invalid = this.ready = true;
|
||||
this.do_update_pager(record.id == null);
|
||||
this.do_update_sidebar();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.attachments.do_update();
|
||||
}
|
||||
if (this.default_focus_field) {
|
||||
this.default_focus_field.focus();
|
||||
}
|
||||
@@ -389,7 +404,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
this.dataset.index = 0;
|
||||
}
|
||||
this.do_update_pager();
|
||||
this.do_update_sidebar();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.attachments.do_update();
|
||||
}
|
||||
this.notification.notify("Record created", "The record has been created with id #" + this.datarecord.id);
|
||||
if (success) {
|
||||
success(_.extend(r, {created: true}));
|
||||
@@ -406,52 +423,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
do_cancel: function () {
|
||||
this.notification.notify("Cancelling form");
|
||||
},
|
||||
do_update_sidebar: function() {
|
||||
if (this.flags.sidebar === false) {
|
||||
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, '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);*/
|
||||
}
|
||||
},
|
||||
on_attachments_loaded: function(attachments) {
|
||||
this.$sidebar = this.view_manager.sidebar.$element.find('.sidebar-attachments');
|
||||
this.attachments = attachments;
|
||||
this.$sidebar.html(QWeb.render('FormView.sidebar.attachments', this));
|
||||
this.$sidebar.find('.oe-sidebar-attachment-delete').click(this.on_attachment_delete);
|
||||
this.$sidebar.find('.oe-binary-file').change(this.on_attachment_changed);
|
||||
},
|
||||
on_attachment_changed: function(e) {
|
||||
window[this.element_id + '_iframe'] = this.do_update_sidebar;
|
||||
var $e = $(e.target);
|
||||
if ($e.val() != '') {
|
||||
this.$sidebar.find('form.oe-binary-form').submit();
|
||||
$e.parent().find('input[type=file]').attr('disabled', 'true');
|
||||
$e.parent().find('button').attr('disabled', 'true').find('img, span').toggle();
|
||||
}
|
||||
},
|
||||
on_attachment_delete: function(e) {
|
||||
var self = this, $e = $(e.currentTarget);
|
||||
var name = _.trim($e.parent().find('a.oe-sidebar-attachments-link').text());
|
||||
if (confirm("Do you really want to delete the attachment " + name + " ?")) {
|
||||
this.rpc('/base/dataset/unlink', {
|
||||
model: 'ir.attachment',
|
||||
ids: [parseInt($e.attr('data-id'))]
|
||||
}, function(r) {
|
||||
$e.parent().remove();
|
||||
self.notification.notify("Delete an attachment", "The attachment '" + name + "' has been deleted");
|
||||
});
|
||||
}
|
||||
},
|
||||
reload: function() {
|
||||
if (this.datarecord.id) {
|
||||
this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded);
|
||||
@@ -472,6 +443,54 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
|
||||
/** @namespace */
|
||||
openerp.base.form = {};
|
||||
|
||||
openerp.base.form.SidebarAttachments = openerp.base.Controller.extend({
|
||||
init: function(parent, element_id, form_view) {
|
||||
this._super(parent, element_id);
|
||||
this.view = form_view;
|
||||
},
|
||||
do_update: function() {
|
||||
if (!this.view.datarecord.id) {
|
||||
this.on_attachments_loaded([]);
|
||||
} else {
|
||||
(new openerp.base.DataSetSearch(
|
||||
this, 'ir.attachment', this.view.dataset.get_context(),
|
||||
[['res_model', '=', this.view.dataset.model],
|
||||
['res_id', '=', this.view.datarecord.id],
|
||||
['type', 'in', ['binary', 'url']]])).read_slice(
|
||||
['name', 'url', 'type'], false, false,
|
||||
this.on_attachments_loaded);
|
||||
}
|
||||
},
|
||||
on_attachments_loaded: function(attachments) {
|
||||
this.attachments = attachments;
|
||||
this.$element.html(QWeb.render('FormView.sidebar.attachments', this));
|
||||
this.$element.find('.oe-binary-file').change(this.on_attachment_changed);
|
||||
this.$element.find('.oe-sidebar-attachment-delete').click(this.on_attachment_delete);
|
||||
},
|
||||
on_attachment_changed: function(e) {
|
||||
window[this.element_id + '_iframe'] = this.do_update;
|
||||
var $e = $(e.target);
|
||||
if ($e.val() != '') {
|
||||
this.$element.find('form.oe-binary-form').submit();
|
||||
$e.parent().find('input[type=file]').attr('disabled', 'true');
|
||||
$e.parent().find('button').attr('disabled', 'true').find('img, span').toggle();
|
||||
}
|
||||
},
|
||||
on_attachment_delete: function(e) {
|
||||
var self = this, $e = $(e.currentTarget);
|
||||
var name = _.trim($e.parent().find('a.oe-sidebar-attachments-link').text());
|
||||
if (confirm("Do you really want to delete the attachment " + name + " ?")) {
|
||||
this.rpc('/base/dataset/unlink', {
|
||||
model: 'ir.attachment',
|
||||
ids: [parseInt($e.attr('data-id'))]
|
||||
}, function(r) {
|
||||
$e.parent().remove();
|
||||
self.notification.notify("Delete an attachment", "The attachment '" + name + "' has been deleted");
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.form.compute_domain = function(expr, fields) {
|
||||
var stack = [];
|
||||
for (var i = expr.length - 1; i >= 0; i--) {
|
||||
@@ -1784,7 +1803,7 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({
|
||||
self.on_ui_change();
|
||||
});
|
||||
|
||||
this.list_view = new openerp.base.form.Many2ManyListView(this.view.view_manager, 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
|
||||
});
|
||||
@@ -1918,7 +1937,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(this,
|
||||
self.view_list = new openerp.base.form.SelectCreateListView(self,
|
||||
self.element_id + "_view_list", self.dataset, false,
|
||||
{'deletable': false});
|
||||
self.view_list.popup = self;
|
||||
@@ -2219,8 +2238,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',
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -89,6 +102,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
*/
|
||||
init: function(parent, element_id, dataset, view_id, options) {
|
||||
this._super(parent, element_id);
|
||||
this.set_default_options();
|
||||
this.view_manager = parent || new openerp.base.NullViewManager();
|
||||
this.dataset = dataset;
|
||||
this.model = dataset.model;
|
||||
@@ -254,9 +268,11 @@ 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);
|
||||
|
||||
if (this.options.sidebar && this.options.sidebar_id) {
|
||||
this.sidebar = new openerp.base.Sidebar(this, this.options.sidebar_id);
|
||||
this.sidebar.start();
|
||||
this.sidebar.add_toolbar(data.fields_view.toolbar);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Configures the ListView pager based on the provided dataset's information
|
||||
@@ -348,16 +364,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,15 +396,20 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
},
|
||||
do_show: function () {
|
||||
this.$element.show();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.$element.show();
|
||||
}
|
||||
if (this.hidden) {
|
||||
this.$element.find('.oe-listview-content').append(
|
||||
this.groups.apoptosis().render());
|
||||
this.hidden = false;
|
||||
}
|
||||
this.view_manager.sidebar.do_refresh(true);
|
||||
},
|
||||
do_hide: function () {
|
||||
this.$element.hide();
|
||||
if (this.sidebar) {
|
||||
this.sidebar.$element.hide();
|
||||
}
|
||||
this.hidden = true;
|
||||
},
|
||||
/**
|
||||
@@ -414,7 +429,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
|
||||
model: this.model,
|
||||
view_id: this.view_id,
|
||||
context: this.dataset.get_context(),
|
||||
toolbar: !!this.flags.sidebar
|
||||
toolbar: this.options.sidebar
|
||||
}, callback);
|
||||
}
|
||||
},
|
||||
@@ -476,6 +491,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();
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -504,11 +520,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)
|
||||
@@ -555,7 +577,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)) {
|
||||
@@ -563,17 +584,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;
|
||||
}
|
||||
});
|
||||
@@ -581,14 +624,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]};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -600,9 +642,9 @@ 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)
|
||||
@@ -667,7 +709,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
|
||||
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) {
|
||||
@@ -805,7 +847,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
|
||||
|
||||
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
|
||||
@@ -980,8 +1022,8 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas
|
||||
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
|
||||
@@ -1085,6 +1127,45 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas
|
||||
});
|
||||
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>');
|
||||
@@ -1103,6 +1184,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas
|
||||
self.children[null] = list;
|
||||
self.elements =
|
||||
[list.$current.replaceAll($element)[0]];
|
||||
self.setup_resequence_rows(list, dataset);
|
||||
if (post_render) { post_render(); }
|
||||
});
|
||||
});
|
||||
|
||||
@@ -110,9 +110,10 @@ 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(this, this.model);
|
||||
@@ -140,31 +141,86 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
||||
return widget.start();
|
||||
}).value();
|
||||
|
||||
// filters management
|
||||
this.$element.find(".oe_search-view-filters-management").change(this.on_filters_management);
|
||||
|
||||
var self = this;
|
||||
$.when.apply(null, widget_starts).then(function () {
|
||||
self.ready.resolve();
|
||||
});
|
||||
|
||||
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 select = this.$element.find(".oe_search-view-filters-management"),
|
||||
val = select.val();
|
||||
select.val("_filters");
|
||||
var self = this;
|
||||
var select = this.$element.find(".oe_search-view-filters-management");
|
||||
var val = select.val();
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -179,8 +235,22 @@ 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 data = this.build_search_data();
|
||||
|
||||
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 = [];
|
||||
@@ -205,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
|
||||
@@ -593,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({
|
||||
@@ -839,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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -11,13 +11,25 @@ openerp.base.ActionManager = openerp.base.Controller.extend({
|
||||
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.
|
||||
// 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) {
|
||||
var self = this;
|
||||
action.flags = _.extend({
|
||||
@@ -49,6 +61,9 @@ 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) {
|
||||
@@ -105,7 +120,6 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
{return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
|
||||
this.views = {};
|
||||
this.flags = this.flags || {};
|
||||
this.sidebar = new openerp.base.NullSidebar();
|
||||
this.registry = openerp.base.views;
|
||||
},
|
||||
/**
|
||||
@@ -119,7 +133,12 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
|
||||
self.on_mode_switch($(this).data('view-type'));
|
||||
});
|
||||
_.each(this.views_src, function(view) {
|
||||
self.views[view.view_type] = $.extend({}, view, {controller: null});
|
||||
self.views[view.view_type] = $.extend({}, view, {
|
||||
controller : null,
|
||||
options : _.extend({
|
||||
sidebar_id : self.element_id + '_sidebar_' + view.view_type
|
||||
}, self.flags)
|
||||
});
|
||||
});
|
||||
if (this.flags.views_switcher === false) {
|
||||
this.$element.find('.oe_vm_switch').hide();
|
||||
@@ -143,7 +162,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.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);
|
||||
@@ -255,13 +274,15 @@ 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(parent, element_id, action) {
|
||||
this.session = parent.session;
|
||||
@@ -282,19 +303,10 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
// Not elegant but allows to avoid flickering of SearchView#do_hide
|
||||
this.flags.search_view = this.flags.pager = this.flags.sidebar = this.flags.action_buttons = false;
|
||||
}
|
||||
if (this.flags.sidebar) {
|
||||
this.sidebar = new openerp.base.Sidebar(null, this);
|
||||
}
|
||||
},
|
||||
start: function() {
|
||||
var inital_view_loaded = this._super();
|
||||
|
||||
// init sidebar
|
||||
if (this.flags.sidebar) {
|
||||
this.$element.find('.view-manager-main-sidebar').html(this.sidebar.render());
|
||||
this.sidebar.start();
|
||||
}
|
||||
|
||||
var search_defaults = {};
|
||||
_.each(this.action.context, function (value, key) {
|
||||
var match = /^search_default_(.*)$/.exec(key);
|
||||
@@ -319,7 +331,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
},
|
||||
stop: function() {
|
||||
// should be replaced by automatic destruction implemented in BaseWidget
|
||||
this.sidebar.stop();
|
||||
this._super();
|
||||
},
|
||||
/**
|
||||
@@ -346,62 +357,88 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.Sidebar = openerp.base.BaseWidget.extend({
|
||||
template: "ViewManager.sidebar",
|
||||
init: function(parent, view_manager) {
|
||||
this._super(parent, view_manager.session);
|
||||
this.view_manager = view_manager;
|
||||
this.sections = [];
|
||||
},
|
||||
set_toolbar: function(toolbar) {
|
||||
this.sections = [];
|
||||
var self = this;
|
||||
_.each([["print", "Reports"], ["action", "Actions"], ["relate", "Links"]], function(type) {
|
||||
if (toolbar[type[0]].length == 0)
|
||||
return;
|
||||
var section = {elements:toolbar[type[0]], label:type[1]};
|
||||
self.sections.push(section);
|
||||
});
|
||||
this.do_refresh(true);
|
||||
},
|
||||
do_refresh: function(new_view) {
|
||||
var view = this.view_manager.active_view;
|
||||
var the_condition = this.sections.length > 0 && _.detect(this.sections,
|
||||
function(x) {return x.elements.length > 0;}) != undefined
|
||||
&& (!new_view || view != 'list');
|
||||
|
||||
this.$element.toggleClass('open-sidebar', the_condition)
|
||||
.toggleClass('closed-sidebar', !the_condition);
|
||||
|
||||
this.$element.html(QWeb.render("ViewManager.sidebar.internal", { sidebar: this, view: view }));
|
||||
|
||||
var self = this;
|
||||
this.$element.find(".toggle-sidebar").click(function(e) {
|
||||
self.$element.toggleClass('open-sidebar closed-sidebar');
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
this.$element.find("a.oe_sidebar_action_a").click(function(e) {
|
||||
var $this = jQuery(this);
|
||||
var index = $this.attr("data-index").split('-');
|
||||
var action = self.sections[index[0]].elements[index[1]];
|
||||
action.flags = {
|
||||
new_window : true
|
||||
};
|
||||
self.session.action_manager.do_action(action);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
openerp.base.Sidebar = openerp.base.Controller.extend({
|
||||
init: function(parent, element_id) {
|
||||
this._super(parent, element_id);
|
||||
this.items = {};
|
||||
},
|
||||
start: function() {
|
||||
this._super();
|
||||
this.do_refresh(false);
|
||||
var self = this;
|
||||
this._super(this, arguments);
|
||||
this.$element.html(QWeb.render('Sidebar'));
|
||||
this.$element.find(".toggle-sidebar").click(function(e) {
|
||||
self.do_toggle();
|
||||
});
|
||||
},
|
||||
add_toolbar: function(toolbar) {
|
||||
var self = this;
|
||||
_.each([['print', "Reports"], ['action', "Actions"], ['relate', "Links"]], function(type) {
|
||||
var items = toolbar[type[0]];
|
||||
if (items.length) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
items[i] = {
|
||||
label: items[i]['name'],
|
||||
action: items[i],
|
||||
classname: 'oe_sidebar_' + type[0]
|
||||
}
|
||||
}
|
||||
self.add_section(type[1], items);
|
||||
}
|
||||
});
|
||||
},
|
||||
add_section: function(name, items) {
|
||||
// For each section, we pass a name/label and optionally an array of items.
|
||||
// If no items are passed, then the section will be created as a custom section
|
||||
// returning back an element_id to be used by a custom controller.
|
||||
// Else, the section is a standard section with items displayed as links.
|
||||
// An item is a dictonary : {
|
||||
// label: label to be displayed for the link,
|
||||
// action: action to be launch when the link is clicked,
|
||||
// callback: a function to be executed when the link is clicked,
|
||||
// classname: optionnal dom class name for the line,
|
||||
// }
|
||||
// Note: The item should have one action or/and a callback
|
||||
var self = this,
|
||||
section_id = _.uniqueId(this.element_id + '_section_');
|
||||
if (items) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
items[i].element_id = _.uniqueId(section_id + '_item_');
|
||||
this.items[items[i].element_id] = items[i];
|
||||
}
|
||||
}
|
||||
var $section = $(QWeb.render("Sidebar.section", {
|
||||
section_id: section_id,
|
||||
name: name,
|
||||
items: items
|
||||
}));
|
||||
if (items) {
|
||||
$section.find('a.oe_sidebar_action_a').click(function() {
|
||||
var item = self.items[$(this).attr('id')];
|
||||
if (item.callback) {
|
||||
item.callback();
|
||||
}
|
||||
if (item.action) {
|
||||
item.action.flags = item.action.flags || {};
|
||||
item.action.flags.new_window = true;
|
||||
self.do_action(item.action);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
$section.appendTo(this.$element.find('div.sidebar-actions'));
|
||||
return section_id;
|
||||
},
|
||||
do_fold: function() {
|
||||
this.$element.addClass('closed-sidebar').removeClass('open-sidebar');
|
||||
},
|
||||
do_unfold: function() {
|
||||
this.$element.addClass('open-sidebar').removeClass('closed-sidebar');
|
||||
},
|
||||
do_toggle: function() {
|
||||
this.$element.toggleClass('open-sidebar closed-sidebar');
|
||||
}
|
||||
});
|
||||
|
||||
openerp.base.NullSidebar = openerp.base.generate_null_object_class(openerp.base.Sidebar);
|
||||
|
||||
openerp.base.Export = openerp.base.Dialog.extend({
|
||||
dialog_title: "Export",
|
||||
template: 'ExportDialog',
|
||||
@@ -422,6 +459,14 @@ openerp.base.Export = openerp.base.Dialog.extend({
|
||||
});
|
||||
|
||||
openerp.base.View = openerp.base.Controller.extend({
|
||||
set_default_options: function(options) {
|
||||
this.options = options || {};
|
||||
_.defaults(this.options, {
|
||||
// All possible views options should be defaulted here
|
||||
sidebar_id: null,
|
||||
sidebar: true
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Fetches and executes the action identified by ``action_data``.
|
||||
*
|
||||
|
||||
@@ -246,7 +246,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">
|
||||
@@ -328,8 +328,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()">
|
||||
@@ -417,10 +417,32 @@
|
||||
</t>
|
||||
</td>
|
||||
<td class="view-manager-main-sidebar" height="100%">
|
||||
<t t-foreach="views" t-as="view">
|
||||
<div t-attf-id="#{prefix}_sidebar_#{view.view_type}" class="sidebar-main-div closed-sidebar" style="display: none"/>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
<t t-name="Sidebar">
|
||||
<a class="toggle-sidebar"></a>
|
||||
<div class="sidebar-content">
|
||||
<div class="sidebar-actions">
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="Sidebar.section">
|
||||
<h2><t t-esc="name"/></h2>
|
||||
<div t-att-id="section_id">
|
||||
<ul t-if="items">
|
||||
<li t-foreach="items" t-as="item" t-att-class="item.classname">
|
||||
<a class="oe_sidebar_action_a" t-att-id="item.element_id" href="#">
|
||||
<t t-esc="item.label"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
<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)"/>
|
||||
<thead class="ui-widget-header">
|
||||
@@ -478,7 +500,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>
|
||||
@@ -545,21 +567,20 @@
|
||||
<t t-raw="frame.render()"/>
|
||||
</t>
|
||||
<t t-name="FormView.sidebar.attachments">
|
||||
<h2>Attachments</h2>
|
||||
<div class="oe-sidebar-attachments-toolbar">
|
||||
<div class="oe-binary-file-set" style="float: right">
|
||||
<form class="oe-binary-form" t-attf-target="#{element_id}_iframe"
|
||||
method="post" enctype="multipart/form-data" action="/base/binary/upload_attachment">
|
||||
<input type="hidden" name="session_id" t-att-value="session.session_id"/>
|
||||
<input type="hidden" name="callback" t-attf-value="#{element_id}_iframe"/>
|
||||
<input type="hidden" name="model" t-att-value="dataset.model"/>
|
||||
<input type="hidden" name="id" t-att-value="datarecord.id"/>
|
||||
<input type="hidden" name="model" t-att-value="view.dataset.model"/>
|
||||
<input type="hidden" name="id" t-att-value="view.datarecord.id"/>
|
||||
<button class="button" type="button">
|
||||
<img src="/base/static/src/img/throbber.gif" width="16" height="16" style="display: none"/>
|
||||
<span>Add</span>
|
||||
</button>
|
||||
<input type="file" class="oe-binary-file" name="ufile" title="Add attachment"
|
||||
t-att-onclick="datarecord.id ? null : 'alert(\'No record selected ! You can only attach to existing record.\'); return false;'"/>
|
||||
t-att-onclick="view.datarecord.id ? null : 'alert(\'No record selected ! You can only attach to existing record.\'); return false;'"/>
|
||||
</form>
|
||||
<iframe t-attf-id="#{element_id}_iframe" t-attf-name="#{element_id}_iframe" style="display: none"> </iframe>
|
||||
</div>
|
||||
@@ -569,7 +590,7 @@
|
||||
<li t-foreach="attachments" t-as="attachment">
|
||||
<t t-if="attachment.type == 'binary'" t-set="attachment.url" t-value="'/base/binary/saveas?session_id='
|
||||
+ session.session_id + '&model=ir.attachment&id=' + attachment.id
|
||||
+ '&field=datas' + '&fieldname=name' + '&t=' + (new Date().getTime())"/>
|
||||
+ '&field=datas&fieldname=name&t=' + (new Date().getTime())"/>
|
||||
<a class="oe-sidebar-attachments-link" t-att-href="attachment.url" target="_blank">
|
||||
<t t-esc="attachment.name"/>
|
||||
</a>
|
||||
@@ -706,7 +727,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>
|
||||
@@ -849,14 +870,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">
|
||||
@@ -1020,29 +1055,6 @@
|
||||
</t>
|
||||
</select>
|
||||
</t>
|
||||
<t t-name="ViewManager.sidebar">
|
||||
<div t-att-id="element_id" class="sidebar-main-div closed-sidebar">
|
||||
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="ViewManager.sidebar.internal">
|
||||
<a class="toggle-sidebar"></a>
|
||||
<div class="sidebar-content">
|
||||
<div class="sidebar-attachments" t-if="view == 'form'"> </div>
|
||||
<div class="sidebar-actions">
|
||||
<t t-foreach="sidebar.sections" t-as="section" t-if="section.elements.length">
|
||||
<h2><t t-esc="section.label"/></h2>
|
||||
<ul>
|
||||
<li t-foreach="section.elements" t-as="element">
|
||||
<a class="oe_sidebar_action_a" t-attf-data-index="#{section_index}-#{element_index}" href="#">
|
||||
<t t-esc="element.name"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="DialogWarning">
|
||||
<table cellspacing="0" cellpadding="0" border="0" class="oe-dialog-warning">
|
||||
<tr>
|
||||
|
||||
@@ -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();
|
||||
},
|
||||
|
||||
@@ -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;"></div>
|
||||
</t>
|
||||
</template>
|
||||
<div t-name="GraphView" t-att-id="elem_id+'-'+chart+'chart'"
|
||||
style="height:300px;position:relative;"/>
|
||||
</template>
|
||||
@@ -407,7 +407,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())
|
||||
@@ -445,7 +445,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