[MERGE] *: stop duplicating web

Avoid duplicating web addon in enterprise by extracting a common basis.
Enterprise features stay in enterprise, but use that common basis.

In web, mainly:
 - JS refactoring and linting
 - Conversion of .sass into .less split into multiple files
 - Templates cleaning and DOM simplification
 - Re-generation of web.pot, and update of .po files

Minor tweaks in some other addons to make them work with this new structure.
This commit is contained in:
Aaron Bohy
2016-04-21 15:21:42 +02:00
committed by Géry Debongnie
169 changed files with 53694 additions and 40431 deletions
@@ -127,9 +127,8 @@
<script type="text/javascript" src="/mail/static/src/js/chat_window.js"></script>
<script type="text/javascript" src="/mail/static/src/js/thread.js"></script>
<script type="text/javascript" src="/im_livechat/static/src/js/im_livechat.js"></script>
<t t-call="web.less_helpers"/>
<link rel="stylesheet" href="/im_livechat/static/src/less/im_livechat_bootstrap.less"/>
<link rel="stylesheet" href="/web/static/src/less/variables.less"/>
<link rel="stylesheet" href="/web/static/src/less/utils.less"/>
<link rel="stylesheet" href="/mail/static/src/less/chat_window.less"></link>
<link rel="stylesheet" href="/mail/static/src/less/thread.less"></link>
<link rel="stylesheet" href="/im_livechat/static/src/less/im_livechat.less"/>
+3
View File
@@ -84,6 +84,9 @@ var FieldPad = form_common.AbstractField.extend(form_common.ReinitializeWidgetMi
}
});
},
is_false: function() {
return false;
}
});
core.form_widget_registry.add('pad', FieldPad);
+1 -7
View File
@@ -54,13 +54,7 @@
</script>
</head>
<body>
<div class='openerp openerp_webclient_container'>
<table class='oe_webclient'>
<tr>
<td class='oe_application' />
</tr>
</table>
</div>
<div class="o_main_content"/>
</body>
</html>
</template>
@@ -1,3 +1,5 @@
@dashboard-bg-color: white;
.o_kanban_view.o_kanban_dashboard.o_salesteam_kanban {
@sale-table-spacing: 10px;
@@ -13,7 +15,7 @@
.o-flex(1, 0, 100%);
padding: 10px (@odoo-horizontal-padding - @sale-table-spacing);
background-color: @odoo-view-background-color;
background-color: @dashboard-bg-color;
position: relative;
.o_welcome_message {
@@ -51,7 +53,7 @@
> tbody > tr > td {
vertical-align: middle;
text-align: center;
border-top: 1px solid @odoo-view-background-color;
border-top: 1px solid @dashboard-bg-color;
width: 25%;
height: 33px;
-3
View File
@@ -1,3 +0,0 @@
{
"directory": "static/lib/"
}
-20
View File
@@ -9,30 +9,10 @@ module.exports = function(grunt) {
laxbreak: true, //unsafe line breaks
},
},
sass: {
dev: {
options: {
style: "expanded",
},
files: {
"static/src/css/base.css": "static/src/css/base.sass",
}
}
},
watch: {
sass: {
files: ["static/src/css/base.sass"],
tasks: ['sass']
},
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('gen', ["sass"]);
grunt.registerTask('watcher', ["gen", "watch"]);
grunt.registerTask('test', []);
grunt.registerTask('default', ['jshint']);
+2 -2
View File
@@ -14,8 +14,8 @@ This module provides the core of the Odoo Web Client.
'data': [
'views/webclient_templates.xml',
],
'qweb' : [
'qweb': [
"static/src/xml/*.xml",
],
'bootstrap': True, # load translations for login screen
'bootstrap': True, # load translations for login screen
}
+8 -8
View File
@@ -427,13 +427,6 @@ def binary_content(xmlid=None, model='ir.attachment', id=None, field='datas', un
xmlid=xmlid, model=model, id=id, field=field, unique=unique, filename=filename, filename_field=filename_field,
download=download, mimetype=mimetype, default_mimetype=default_mimetype, env=env)
def db_info():
version_info = openerp.service.common.exp_version()
return {
'server_version': version_info.get('server_version'),
'server_version_info': version_info.get('server_version_info'),
}
#----------------------------------------------------------
# OpenERP Web web Controllers
#----------------------------------------------------------
@@ -454,7 +447,14 @@ class Home(http.Controller):
request.uid = request.session.uid
menu_data = request.registry['ir.ui.menu'].load_menus(request.cr, request.uid, request.debug, context=request.context)
return request.render('web.webclient_bootstrap', qcontext={'menu_data': menu_data, 'db_info': json.dumps(db_info())})
version_info = openerp.service.common.exp_version()
db_info = {
'server_version': version_info.get('server_version'),
'server_version_info': version_info.get('server_version_info'),
}
return request.render('web.webclient_bootstrap', qcontext={'menu_data': menu_data, 'db_info': json.dumps(db_info)})
@http.route('/web/dbredirect', type='http', auth="none")
def web_db_redirect(self, redirect='/', **kw):
+2 -2
View File
@@ -46,7 +46,7 @@ various situations:
Action button (``button`` tag in the view) inside the cell
``.oe_readonly``
``.o_readonly``
Readonly field cell
@@ -66,7 +66,7 @@ Editable list view
The editable list view module adds a few supplementary style hook
classes, for edition situations:
``.oe_list_editable``
``.o_list_editable``
Added to the ``.oe_list`` when the list is editable (however that
was done). The class may be removed on-the-fly if the list becomes
+712 -538
View File
File diff suppressed because it is too large Load Diff
+750 -570
View File
File diff suppressed because it is too large Load Diff
+721 -547
View File
File diff suppressed because it is too large Load Diff
+720 -546
View File
File diff suppressed because it is too large Load Diff
+747 -569
View File
File diff suppressed because it is too large Load Diff
+712 -538
View File
File diff suppressed because it is too large Load Diff
+748 -570
View File
File diff suppressed because it is too large Load Diff
+745 -567
View File
File diff suppressed because it is too large Load Diff
+746 -568
View File
File diff suppressed because it is too large Load Diff
+750 -572
View File
File diff suppressed because it is too large Load Diff
+732 -554
View File
File diff suppressed because it is too large Load Diff
+746 -568
View File
File diff suppressed because it is too large Load Diff
+737 -559
View File
File diff suppressed because it is too large Load Diff
+749 -571
View File
File diff suppressed because it is too large Load Diff
+710 -536
View File
File diff suppressed because it is too large Load Diff
+741 -559
View File
File diff suppressed because it is too large Load Diff
+720 -546
View File
File diff suppressed because it is too large Load Diff
+740 -559
View File
File diff suppressed because it is too large Load Diff
+735 -557
View File
File diff suppressed because it is too large Load Diff
+734 -556
View File
File diff suppressed because it is too large Load Diff
+709 -535
View File
File diff suppressed because it is too large Load Diff
+719 -545
View File
File diff suppressed because it is too large Load Diff
+710 -536
View File
File diff suppressed because it is too large Load Diff
+728 -551
View File
File diff suppressed because it is too large Load Diff
+749 -571
View File
File diff suppressed because it is too large Load Diff
+743 -561
View File
File diff suppressed because it is too large Load Diff
+720 -546
View File
File diff suppressed because it is too large Load Diff
+711 -537
View File
File diff suppressed because it is too large Load Diff
+727 -553
View File
File diff suppressed because it is too large Load Diff
+709 -535
View File
File diff suppressed because it is too large Load Diff
+750 -572
View File
File diff suppressed because it is too large Load Diff
+742 -558
View File
File diff suppressed because it is too large Load Diff
+750 -576
View File
File diff suppressed because it is too large Load Diff
+740 -560
View File
File diff suppressed because it is too large Load Diff
+736 -558
View File
File diff suppressed because it is too large Load Diff
+726 -552
View File
File diff suppressed because it is too large Load Diff
+723 -549
View File
File diff suppressed because it is too large Load Diff
+749 -571
View File
File diff suppressed because it is too large Load Diff
+872 -504
View File
File diff suppressed because it is too large Load Diff
+735 -561
View File
File diff suppressed because it is too large Load Diff
+710 -536
View File
File diff suppressed because it is too large Load Diff
+749 -571
View File
File diff suppressed because it is too large Load Diff
+749 -571
View File
File diff suppressed because it is too large Load Diff
+747 -569
View File
File diff suppressed because it is too large Load Diff
+739 -557
View File
File diff suppressed because it is too large Load Diff
+725 -551
View File
File diff suppressed because it is too large Load Diff
+751 -573
View File
File diff suppressed because it is too large Load Diff
+744 -566
View File
File diff suppressed because it is too large Load Diff
+747 -565
View File
File diff suppressed because it is too large Load Diff
+749 -571
View File
File diff suppressed because it is too large Load Diff
+737 -559
View File
File diff suppressed because it is too large Load Diff
+740 -558
View File
File diff suppressed because it is too large Load Diff
+749 -571
View File
File diff suppressed because it is too large Load Diff
+709 -535
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+735 -561
View File
File diff suppressed because it is too large Load Diff
+747 -567
View File
File diff suppressed because it is too large Load Diff
+737 -559
View File
File diff suppressed because it is too large Load Diff
+739 -557
View File
File diff suppressed because it is too large Load Diff
+724 -550
View File
File diff suppressed because it is too large Load Diff
+700 -510
View File
File diff suppressed because it is too large Load Diff
+751 -567
View File
File diff suppressed because it is too large Load Diff
+728 -550
View File
File diff suppressed because it is too large Load Diff
-587
View File
@@ -1,587 +0,0 @@
/*!
* Bootstrap v3.3.5 (http://getbootstrap.com)
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
}
.btn-default:active,
.btn-primary:active,
.btn-success:active,
.btn-info:active,
.btn-warning:active,
.btn-danger:active,
.btn-default.active,
.btn-primary.active,
.btn-success.active,
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
}
.btn-default.disabled,
.btn-primary.disabled,
.btn-success.disabled,
.btn-info.disabled,
.btn-warning.disabled,
.btn-danger.disabled,
.btn-default[disabled],
.btn-primary[disabled],
.btn-success[disabled],
.btn-info[disabled],
.btn-warning[disabled],
.btn-danger[disabled],
fieldset[disabled] .btn-default,
fieldset[disabled] .btn-primary,
fieldset[disabled] .btn-success,
fieldset[disabled] .btn-info,
fieldset[disabled] .btn-warning,
fieldset[disabled] .btn-danger {
-webkit-box-shadow: none;
box-shadow: none;
}
.btn-default .badge,
.btn-primary .badge,
.btn-success .badge,
.btn-info .badge,
.btn-warning .badge,
.btn-danger .badge {
text-shadow: none;
}
.btn:active,
.btn.active {
background-image: none;
}
.btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #dbdbdb;
border-color: #ccc;
}
.btn-default:hover,
.btn-default:focus {
background-color: #e0e0e0;
background-position: 0 -15px;
}
.btn-default:active,
.btn-default.active {
background-color: #e0e0e0;
border-color: #dbdbdb;
}
.btn-default.disabled,
.btn-default[disabled],
fieldset[disabled] .btn-default,
.btn-default.disabled:hover,
.btn-default[disabled]:hover,
fieldset[disabled] .btn-default:hover,
.btn-default.disabled:focus,
.btn-default[disabled]:focus,
fieldset[disabled] .btn-default:focus,
.btn-default.disabled.focus,
.btn-default[disabled].focus,
fieldset[disabled] .btn-default.focus,
.btn-default.disabled:active,
.btn-default[disabled]:active,
fieldset[disabled] .btn-default:active,
.btn-default.disabled.active,
.btn-default[disabled].active,
fieldset[disabled] .btn-default.active {
background-color: #e0e0e0;
background-image: none;
}
.btn-primary {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #245580;
}
.btn-primary:hover,
.btn-primary:focus {
background-color: #265a88;
background-position: 0 -15px;
}
.btn-primary:active,
.btn-primary.active {
background-color: #265a88;
border-color: #245580;
}
.btn-primary.disabled,
.btn-primary[disabled],
fieldset[disabled] .btn-primary,
.btn-primary.disabled:hover,
.btn-primary[disabled]:hover,
fieldset[disabled] .btn-primary:hover,
.btn-primary.disabled:focus,
.btn-primary[disabled]:focus,
fieldset[disabled] .btn-primary:focus,
.btn-primary.disabled.focus,
.btn-primary[disabled].focus,
fieldset[disabled] .btn-primary.focus,
.btn-primary.disabled:active,
.btn-primary[disabled]:active,
fieldset[disabled] .btn-primary:active,
.btn-primary.disabled.active,
.btn-primary[disabled].active,
fieldset[disabled] .btn-primary.active {
background-color: #265a88;
background-image: none;
}
.btn-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #3e8f3e;
}
.btn-success:hover,
.btn-success:focus {
background-color: #419641;
background-position: 0 -15px;
}
.btn-success:active,
.btn-success.active {
background-color: #419641;
border-color: #3e8f3e;
}
.btn-success.disabled,
.btn-success[disabled],
fieldset[disabled] .btn-success,
.btn-success.disabled:hover,
.btn-success[disabled]:hover,
fieldset[disabled] .btn-success:hover,
.btn-success.disabled:focus,
.btn-success[disabled]:focus,
fieldset[disabled] .btn-success:focus,
.btn-success.disabled.focus,
.btn-success[disabled].focus,
fieldset[disabled] .btn-success.focus,
.btn-success.disabled:active,
.btn-success[disabled]:active,
fieldset[disabled] .btn-success:active,
.btn-success.disabled.active,
.btn-success[disabled].active,
fieldset[disabled] .btn-success.active {
background-color: #419641;
background-image: none;
}
.btn-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #28a4c9;
}
.btn-info:hover,
.btn-info:focus {
background-color: #2aabd2;
background-position: 0 -15px;
}
.btn-info:active,
.btn-info.active {
background-color: #2aabd2;
border-color: #28a4c9;
}
.btn-info.disabled,
.btn-info[disabled],
fieldset[disabled] .btn-info,
.btn-info.disabled:hover,
.btn-info[disabled]:hover,
fieldset[disabled] .btn-info:hover,
.btn-info.disabled:focus,
.btn-info[disabled]:focus,
fieldset[disabled] .btn-info:focus,
.btn-info.disabled.focus,
.btn-info[disabled].focus,
fieldset[disabled] .btn-info.focus,
.btn-info.disabled:active,
.btn-info[disabled]:active,
fieldset[disabled] .btn-info:active,
.btn-info.disabled.active,
.btn-info[disabled].active,
fieldset[disabled] .btn-info.active {
background-color: #2aabd2;
background-image: none;
}
.btn-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #e38d13;
}
.btn-warning:hover,
.btn-warning:focus {
background-color: #eb9316;
background-position: 0 -15px;
}
.btn-warning:active,
.btn-warning.active {
background-color: #eb9316;
border-color: #e38d13;
}
.btn-warning.disabled,
.btn-warning[disabled],
fieldset[disabled] .btn-warning,
.btn-warning.disabled:hover,
.btn-warning[disabled]:hover,
fieldset[disabled] .btn-warning:hover,
.btn-warning.disabled:focus,
.btn-warning[disabled]:focus,
fieldset[disabled] .btn-warning:focus,
.btn-warning.disabled.focus,
.btn-warning[disabled].focus,
fieldset[disabled] .btn-warning.focus,
.btn-warning.disabled:active,
.btn-warning[disabled]:active,
fieldset[disabled] .btn-warning:active,
.btn-warning.disabled.active,
.btn-warning[disabled].active,
fieldset[disabled] .btn-warning.active {
background-color: #eb9316;
background-image: none;
}
.btn-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #b92c28;
}
.btn-danger:hover,
.btn-danger:focus {
background-color: #c12e2a;
background-position: 0 -15px;
}
.btn-danger:active,
.btn-danger.active {
background-color: #c12e2a;
border-color: #b92c28;
}
.btn-danger.disabled,
.btn-danger[disabled],
fieldset[disabled] .btn-danger,
.btn-danger.disabled:hover,
.btn-danger[disabled]:hover,
fieldset[disabled] .btn-danger:hover,
.btn-danger.disabled:focus,
.btn-danger[disabled]:focus,
fieldset[disabled] .btn-danger:focus,
.btn-danger.disabled.focus,
.btn-danger[disabled].focus,
fieldset[disabled] .btn-danger.focus,
.btn-danger.disabled:active,
.btn-danger[disabled]:active,
fieldset[disabled] .btn-danger:active,
.btn-danger.disabled.active,
.btn-danger[disabled].active,
fieldset[disabled] .btn-danger.active {
background-color: #c12e2a;
background-image: none;
}
.thumbnail,
.img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
background-color: #e8e8e8;
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
background-color: #2e6da4;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
.navbar-default {
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
}
.navbar-default .navbar-nav > .open > a,
.navbar-default .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
}
.navbar-brand,
.navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
}
.navbar-inverse {
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-radius: 4px;
}
.navbar-inverse .navbar-nav > .open > a,
.navbar-inverse .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
}
.navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
}
.navbar-static-top,
.navbar-fixed-top,
.navbar-fixed-bottom {
border-radius: 0;
}
@media (max-width: 767px) {
.navbar .navbar-nav .open .dropdown-menu > .active > a,
.navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
color: #fff;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
}
.alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
}
.alert-success {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
background-repeat: repeat-x;
border-color: #b2dba1;
}
.alert-info {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
background-repeat: repeat-x;
border-color: #9acfea;
}
.alert-warning {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
background-repeat: repeat-x;
border-color: #f5e79e;
}
.alert-danger {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
background-repeat: repeat-x;
border-color: #dca7a7;
}
.progress {
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-striped {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
}
.list-group {
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}
.list-group-item.active,
.list-group-item.active:hover,
.list-group-item.active:focus {
text-shadow: 0 -1px 0 #286090;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
background-repeat: repeat-x;
border-color: #2b669a;
}
.list-group-item.active .badge,
.list-group-item.active:hover .badge,
.list-group-item.active:focus .badge {
text-shadow: none;
}
.panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}
.panel-default > .panel-heading {
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.panel-primary > .panel-heading {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
.panel-success > .panel-heading {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
background-repeat: repeat-x;
}
.panel-info > .panel-heading {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
background-repeat: repeat-x;
}
.panel-warning > .panel-heading {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
background-repeat: repeat-x;
}
.panel-danger > .panel-heading {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
background-repeat: repeat-x;
}
.well {
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
border-color: #dcdcdc;
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
}
/*# sourceMappingURL=bootstrap-theme.css.map */
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored Executable → Regular
View File
@@ -1,5 +0,0 @@
repo: 076b192d0d8ab2b92d1dbcfa3da055382f30eaea
node: 7ee0bc7b4e9138f485cdc9ec791961d8ef452f17
branch: default
latesttag: 0.7
latesttagdistance: 11
-89
View File
@@ -1,89 +0,0 @@
.openerp .oe_export {
width: 100%;
}
/* Customize according bootstrap3 */
.openerp .oe_export label {
font-weight: normal;
}
/* End of customize */
.openerp .oe_export_row tr{
background-color: #FFFFFF;
font-size: 0.8em;
height: 22px;
}
.openerp tr.ui-selected td {
background-color: #CCCCCC;
}
.openerp .oe_export_requiredfield {
background-color: #D2D2FF;
}
.openerp .oe_export_readonlyfield{
background-color: #999999;
}
.openerp .oe_export_row:hover{
background-color: #F3F3F3;
}
.openerp .oe_export_fields_selector_left {
width: 50%;
}
.openerp div#left_field_panel {
overflow: scroll;
width: 100%;
height: 400px;
border: solid #999999 1px;
}
.openerp div#left_field_panel table {
width: 100%;
}
.openerp .oe_export_fields_selector_center {
text-align: center;
}
.openerp .oe_export_fields_selector_center button {
white-space: nowrap;
}
.openerp .oe_export_fields_selector_right {
width: 45%;
height: 400px;
}
.openerp .oe_export_fields_selector_right select{
width: 100%;
height: 100%;
}
.openerp .oe_export_tree_header{
border: 0.5px solid #E3E3E3;
text-align: left;
white-space: nowrap;
padding: 4px 5px;
background: url(/web/static/src/img/header.gif);
}
.openerp table.tree_grid{
border: 1px solid #E3E3E3;
text-align: left;
white-space: nowrap;
background-color:#E3E3E3;
border-collapse: collapse;
width: 100%;
}
.openerp table.tree_grid a:hover {
color: blue;
border: none;
}
.openerp table.tree_grid a {
color: #5F5C5C;
border: none;
display: block;
}
-12
View File
@@ -1,12 +0,0 @@
/* This css contains the styling specific to the 'normal mode'. (as opposite to the embedded mode) */
/* In embedded mode [1], this stylesheet won't be loaded. */
/* [1] The web client features an embedded mode in which the webclient */
/* or a part of it can be started in any element of any webpage host. */
body {
padding: 0;
margin: 0;
overflow-y: scroll;
height: 100%;
}
-29
View File
@@ -1,29 +0,0 @@
/** base */
.openerp .oe_form label + .oe_form_field.oe_form_field_one2many {
display: block;
}
.openerp .oe_leftbar > div > div > div > div.oe_secondary_menus_container {
position: static;
}
.openerp .oe_application > div > .oe_view_manager > .oe_view_manager_wrapper > div > .oe_view_manager_body {
position: static;
}
/** web_calendar */
.fc .ui-draggable-dragging .fc-event-bg, /* TODO: something nicer like .fc-opacity */
.fc-select-helper .fc-event-bg {
display: none; /* for IE6/7/8. nested opacity filters while dragging don't work */
}
/** web_graph */
.openerp svg:not(:root) { /* width and height are not take in consideration */
overflow: visible;
}
.graph_main_content.graph_chart_mode > div > svg {
min-height: 521px;
}
/** web_kanban */
.openerp .oe_kanban_column_cards {
min-height: 80px;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 B

@@ -0,0 +1,245 @@
odoo.define('web.AbstractWebClient', function (require) {
"use strict";
var ActionManager = require('web.ActionManager');
var core = require('web.core');
var crash_manager = require('web.crash_manager');
var Loading = require('web.Loading');
var NotificationManager = require('web.notification').NotificationManager;
var session = require('web.session');
var utils = require('web.utils');
var Widget = require('web.Widget');
var _t = core._t;
var WebClient = Widget.extend({
custom_events: {
notification: function (e) {
if(this.notification_manager) {
this.notification_manager.notify(e.data.title, e.data.message, e.data.sticky);
}
},
warning: function (e) {
if(this.notification_manager) {
this.notification_manager.warn(e.data.title, e.data.message, e.data.sticky);
}
},
clear_uncommitted_changes: function (e) {
this.clear_uncommitted_changes().then(e.data.callback);
},
},
init: function(parent, client_options) {
this.client_options = {};
this._super(parent);
this.origin = undefined;
if (client_options) {
_.extend(this.client_options, client_options);
}
this._current_state = null;
this.menu_dm = new utils.DropMisordered();
this.action_mutex = new utils.Mutex();
this.set('title_part', {"zopenerp": "Odoo"});
},
start: function() {
var self = this;
this.on("change:title_part", this, this._title_changed);
this._title_changed();
return session.session_bind(this.origin)
.then(function () {
self.bind_events();
return $.when(
self.set_action_manager(),
self.set_notification_manager(),
self.set_loading()
);
}).then(function () {
if (session.session_is_valid()) {
return self.show_application();
} else {
// database manager needs the webclient to keep going even
// though it has no valid session
return $.when();
}
}).then(function () {
if (self.client_options.action) {
self.do_action(self.client_options.action);
delete(self.client_options.action);
}
core.bus.trigger('web_client_ready');
});
},
bind_events: function() {
var self = this;
$('.oe_systray').show();
this.$el.on('mouseenter', '.oe_systray > div:not([data-toggle=tooltip])', function() {
$(this).attr('data-toggle', 'tooltip').tooltip().trigger('mouseenter');
});
this.$el.on('click', '.oe_dropdown_toggle', function(ev) {
ev.preventDefault();
var $toggle = $(this);
var doc_width = $(document).width();
var $menu = $toggle.siblings('.oe_dropdown_menu');
$menu = $menu.size() >= 1 ? $menu : $toggle.find('.oe_dropdown_menu');
var state = $menu.is('.oe_opened');
setTimeout(function() {
// Do not alter propagation
$toggle.add($menu).toggleClass('oe_opened', !state);
if (!state) {
// Move $menu if outside window's edge
var offset = $menu.offset();
var menu_width = $menu.width();
var x = doc_width - offset.left - menu_width - 2;
if (x < 0) {
$menu.offset({ left: offset.left + x }).width(menu_width);
}
}
}, 0);
});
core.bus.on('click', this, function(ev) {
$('.tooltip').remove();
if (!$(ev.target).is('input[type=file]')) {
self.$('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened');
}
});
core.bus.on('set_full_screen', this, function (full_screen) {
this.set_content_full_screen(full_screen);
});
core.bus.on('connection_lost', this, this.on_connection_lost);
core.bus.on('connection_restored', this, this.on_connection_restored);
// crash manager integration
session.on('error', crash_manager, crash_manager.rpc_error);
window.onerror = function (message, file, line, col, error) {
var traceback = error ? error.stack : '';
crash_manager.show_error({
type: _t("Client Error"),
message: message,
data: {debug: file + ':' + line + "\n" + _t('Traceback:') + "\n" + traceback}
});
};
},
set_action_manager: function() {
this.action_manager = new ActionManager(this, {webclient: this});
return this.action_manager.appendTo(this.$('.o_main_content'));
},
set_notification_manager: function() {
this.notification_manager = new NotificationManager(this);
return this.notification_manager.appendTo(this.$el);
},
set_loading: function() {
this.loading = new Loading(this);
return this.loading.appendTo(this.$el);
},
show_application: function() {
},
clear_uncommitted_changes: function() {
var def = $.Deferred().resolve();
core.bus.trigger('clear_uncommitted_changes', function chain_callbacks(callback) {
def = def.then(callback);
});
return def;
},
destroy_content: function() {
_.each(_.clone(this.getChildren()), function(el) {
el.destroy();
});
this.$el.children().remove();
},
// --------------------------------------------------------------
// Window title handling
// --------------------------------------------------------------
/**
Sets the first part of the title of the window, dedicated to the current action.
*/
set_title: function(title) {
this.set_title_part("action", title);
},
/**
Sets an arbitrary part of the title of the window. Title parts are identified by strings. Each time
a title part is changed, all parts are gathered, ordered by alphabetical order and displayed in the
title of the window separated by '-'.
*/
set_title_part: function(part, title) {
var tmp = _.clone(this.get("title_part"));
tmp[part] = title;
this.set("title_part", tmp);
},
_title_changed: function() {
var parts = _.sortBy(_.keys(this.get("title_part")), function(x) { return x; });
var tmp = "";
_.each(parts, function(part) {
var str = this.get("title_part")[part];
if (str) {
tmp = tmp ? tmp + " - " + str : str;
}
}, this);
document.title = tmp;
},
// --------------------------------------------------------------
// do_*
// --------------------------------------------------------------
/**
* When do_action is performed on the WebClient, forward it to the main ActionManager
* This allows to widgets that are not inside the ActionManager to perform do_action
*/
do_action: function() {
return this.action_manager.do_action.apply(this, arguments);
},
do_reload: function() {
var self = this;
return this.session.session_reload().then(function () {
session.load_modules(true).then(
self.menu.proxy('do_reload'));
});
},
do_push_state: function(state) {
if ('title' in state) {
this.set_title(state.title);
delete state.title;
}
var url = '#' + $.param(state);
this._current_state = $.deparam($.param(state), false); // stringify all values
$.bbq.pushState(url);
this.trigger('state_pushed', state);
},
// --------------------------------------------------------------
// Connection notifications
// --------------------------------------------------------------
on_connection_lost: function () {
this.connection_notification = this.notification_manager.notify(
_t('Connection lost'),
_t('Trying to reconnect...'),
true
);
},
on_connection_restored: function () {
if (this.connection_notification) {
this.connection_notification.destroy();
this.notification_manager.notify(
_t('Connection restored'),
_t('You are back online'),
false
);
this.connection_notification = false;
}
},
// --------------------------------------------------------------
// Scrolltop handling
// --------------------------------------------------------------
get_scrollTop: function () {
},
//--------------------------------------------------------------
// Misc.
//--------------------------------------------------------------
set_content_full_screen: function(fullscreen) {
$(document.body).css('overflow-y', fullscreen ? 'hidden' : 'scroll');
this.$('.oe_webclient').toggleClass(
'oe_content_full_screen', fullscreen);
},
});
return WebClient;
});
+112 -100
View File
@@ -22,25 +22,18 @@ var Action = core.Class.extend({
this.action_descr = action;
this.title = action.display_name || action.name;
},
/**
* Not implemented for client actions
* @return {Deferred} a rejected Deferred
*/
appendTo: function() {
return $.Deferred().reject();
},
/**
* This method should restore this previously loaded action
* Calls on_reverse_breadcrumb callback if defined
* Calls on_reverse_breadcrumb_callback if defined
* @return {Deferred} resolved when widget is enabled
*/
restore: function() {
if (this.on_reverse_breadcrumb) {
return this.on_reverse_breadcrumb();
if (this.on_reverse_breadcrumb_callback) {
return this.on_reverse_breadcrumb_callback();
}
},
/**
* Not implemented for functions
* There is nothing to detach in the case of a client function
*/
detach: function() {
},
@@ -50,11 +43,16 @@ var Action = core.Class.extend({
destroy: function() {
},
/**
* Sets the on_reverse_breadcrumb callback to be called when coming back to that action
* @param {Function} [on_reverse_breadcrumb] the callback
* Sets the on_reverse_breadcrumb_callback to be called when coming back to that action
* @param {Function} [callback] the callback
*/
set_on_reverse_breadcrumb: function(on_reverse_breadcrumb) {
this.on_reverse_breadcrumb = on_reverse_breadcrumb;
set_on_reverse_breadcrumb: function(callback) {
this.on_reverse_breadcrumb_callback = callback;
},
/**
* Not implemented for client actions
*/
set_scrollTop: function() {
},
/**
* Stores the DOM fragment of the action
@@ -65,8 +63,10 @@ var Action = core.Class.extend({
},
/**
* Not implemented for client actions
* @return {int} the number of pixels the webclient is scrolled when leaving the action
*/
set_is_in_DOM: function() {
get_scrollTop: function() {
return 0;
},
/**
* @return {Object} the description of the action
@@ -112,16 +112,6 @@ var WidgetAction = Action.extend({
this.title = widget.get('title');
});
},
/**
* Wraps the action's widget in a container and appends it to el
* @param {DocumentFragment} [el] where to append the widget
* @return {Deferred} resolved when the widget is appended
*/
appendTo: function(el) {
this.$client_action_container = $('<div>').addClass('oe_client_action');
this.$client_action_container.appendTo(el);
return this.widget.appendTo(this.$client_action_container);
},
/**
* Restores WidgetAction by calling do_show on its widget
*/
@@ -132,32 +122,26 @@ var WidgetAction = Action.extend({
});
},
/**
* Detaches the client action's container from the DOM
* @return {jQuery} the action's container
* Detaches the action's widget from the DOM
* @return the widget's $el
*/
detach: function() {
return this.$client_action_container.detach();
// Hack to remove badly inserted nvd3 tooltips ; should be removed when upgrading nvd3 lib
$('body > .nvtooltip').remove();
return framework.detach([{widget: this.widget}]);
},
/**
* Destroys the widget
*/
destroy: function() {
this.widget.destroy();
this.detach();
},
});
/**
* Specialization of WidgetAction for window actions (i.e. ViewManagers)
*/
var ViewManagerAction = WidgetAction.extend({
/**
* Appends the action's widget to el
* @param {DocumentFragment} [el] where to append the widget
* @return {Deferred} resolved when the widget is appended
*/
appendTo: function(el) {
return this.widget.appendTo(el);
},
/**
* Restores a ViewManagerAction
* Switches to the requested view by calling select_view on the ViewManager
@@ -170,27 +154,27 @@ var ViewManagerAction = WidgetAction.extend({
});
},
/**
* Sets is_in_DOM on this.widget
* @param {Boolean} [is_in_DOM] true iff the widget is attached in the DOM
* Sets the on_reverse_breadcrumb_callback and the scrollTop to apply when
* coming back to that action
* @param {Function} [callback] the callback
* @param {int} [scrollTop] the number of pixels to scroll
*/
set_is_in_DOM: function(is_in_DOM) {
this.widget.is_in_DOM = is_in_DOM;
set_on_reverse_breadcrumb: function(callback, scrollTop) {
this._super(callback);
this.set_scrollTop(scrollTop);
},
/**
* Detaches the view_manager from the DOM
* @return {jQuery} the view_manager's $el
* Sets the scroll position of the widgets's active_view
* @param {int} [scrollTop] the number of pixels to scroll
*/
detach: function() {
// Hack to remove badly inserted nvd3 tooltips ; should be removed when upgrading nvd3 lib
$('body > .nvtooltip').remove();
return this.widget.$el.detach();
set_scrollTop: function(scrollTop) {
this.widget.active_view.controller.set_scrollTop(scrollTop);
},
/**
* Destroys the widget
* @return {int} the number of pixels the webclient is scrolled when leaving the action
*/
destroy: function() {
this.widget.destroy();
get_scrollTop: function() {
return this.widget.active_view.controller.get_scrollTop();
},
/**
* @return {Array} array of Objects that will be interpreted to display the breadcrumbs
@@ -214,13 +198,31 @@ var ViewManagerAction = WidgetAction.extend({
});
var ActionManager = Widget.extend({
template: "ActionManager",
init: function(parent) {
template: 'ActionManager',
/**
* Called each time the action manager is attached into the DOM
*/
on_attach_callback: function() {
this.is_in_DOM = true;
if (this.inner_widget && this.inner_widget.on_attach_callback) {
this.inner_widget.on_attach_callback();
}
},
/**
* Called each time the action manager is detached from the DOM
*/
on_detach_callback: function() {
this.is_in_DOM = false;
if (this.inner_widget && this.inner_widget.on_detach_callback) {
this.inner_widget.on_detach_callback();
}
},
init: function(parent, options) {
this._super(parent);
this.action_stack = [];
this.inner_action = null;
this.inner_widget = null;
this.webclient = parent;
this.webclient = options && options.webclient;
this.dialog = null;
this.dialog_widget = null;
this.on('history_back', this, this.proxy('history_back'));
@@ -236,8 +238,15 @@ var ActionManager = Widget.extend({
this.select_action(action, index);
}, 200, true));
// Append the main control panel to the DOM (inside the ActionManager jQuery element)
this.main_control_panel.appendTo(this.$el);
// Listen to event "DOM_updated" to restore the scroll position
core.bus.on('DOM_updated', this, function() {
if (this.inner_action) {
this.trigger_up('scrollTo', {offset: this.inner_action.get_scrollTop() || 0});
}
});
// Insert the main control panel into the DOM
return this.main_control_panel.insertBefore(this.$el);
},
dialog_stop: function (reason) {
if (this.dialog) {
@@ -256,9 +265,9 @@ var ActionManager = Widget.extend({
*/
push_action: function(widget, action_descr, options) {
var self = this;
var old_widget = this.inner_widget;
var old_action = this.inner_action;
var old_action_stack = this.action_stack;
var old_action = this.inner_action;
var old_widget = this.inner_widget;
options = options || {};
// Empty action_stack if requested
@@ -277,8 +286,8 @@ var ActionManager = Widget.extend({
}
// Set on_reverse_breadcrumb callback on previous inner_action
if (old_action) {
old_action.set_on_reverse_breadcrumb(options.on_reverse_breadcrumb);
if (this.webclient && old_action) {
old_action.set_on_reverse_breadcrumb(options.on_reverse_breadcrumb, this.webclient.get_scrollTop());
}
// Update action_stack (must be done before appendTo to properly
@@ -295,25 +304,19 @@ var ActionManager = Widget.extend({
// render the inner_widget in a fragment, and append it to the
// document only when it's ready
var new_widget_fragment = document.createDocumentFragment();
return $.when(this.inner_action.appendTo(new_widget_fragment)).done(function() {
return $.when(this.inner_widget.appendTo(new_widget_fragment)).done(function() {
// Detach the fragment of the previous action and store it within the action
if (old_action) {
old_action.set_fragment(old_action.detach());
old_action.set_is_in_DOM(false);
}
if (!widget.need_control_panel) {
// Hide the main ControlPanel for widgets that do not use it
self.main_control_panel.do_hide();
}
framework.append(self.$el, new_widget_fragment, true);
self.inner_action.set_is_in_DOM(true);
// Hide the old_widget as it will be removed from the DOM when it
// is destroyed
if (old_widget) {
old_widget.do_hide();
}
framework.append(self.$el, new_widget_fragment, {
in_DOM: self.is_in_DOM,
callbacks: [{widget: self.inner_widget}],
});
if (options.clear_breadcrumbs) {
self.clear_action_stack(old_action_stack);
}
@@ -325,6 +328,11 @@ var ActionManager = Widget.extend({
self.inner_widget = old_widget;
});
},
set_scrollTop: function(scrollTop) {
if (this.inner_action) {
this.inner_action.set_scrollTop(scrollTop);
}
},
get_breadcrumbs: function () {
return _.flatten(_.map(this.action_stack, function (action) {
return action.get_breadcrumbs();
@@ -368,7 +376,9 @@ var ActionManager = Widget.extend({
},
select_action: function(action, index) {
var self = this;
return this.webclient.clear_uncommitted_changes().then(function() {
var def = this.webclient && this.webclient.clear_uncommitted_changes() || $.when();
return def.then(function() {
// Set the new inner_action/widget and update the action stack
var old_action = self.inner_action;
var action_index = self.action_stack.indexOf(action);
@@ -376,19 +386,21 @@ var ActionManager = Widget.extend({
self.inner_action = action;
self.inner_widget = action.widget;
// Hide the ControlPanel if the widget doesn't use it
if (!self.inner_widget.need_control_panel) {
self.main_control_panel.do_hide();
}
return $.when(action.restore(index)).done(function() {
// Hide the ControlPanel if the widget doesn't use it
if (!self.inner_widget.need_control_panel) {
self.main_control_panel.do_hide();
}
// Attach the DOM of the action and restore the scroll position only if necessary
if (action !== old_action) {
// Clear the action stack (this also removes the current action from the DOM)
self.clear_action_stack(to_destroy);
// Append the fragment of the action to restore to self.$el
framework.append(self.$el, action.get_fragment(), true);
self.inner_action.set_is_in_DOM(true);
framework.append(self.$el, action.get_fragment(), {
in_DOM: self.is_in_DOM,
callbacks: [{widget: action.widget}],
});
}
});
}).fail(function() {
@@ -406,7 +418,7 @@ var ActionManager = Widget.extend({
}
},
do_push_state: function(state) {
if (!this.webclient || !this.webclient.do_push_state || this.dialog) {
if (!this.webclient || this.dialog) {
return;
}
state = state || {};
@@ -491,13 +503,6 @@ var ActionManager = Widget.extend({
res_id: state.id,
view_type: state.view_type,
});
$.when(action_loaded || null).done(function() {
self.webclient.menu.is_bound.done(function() {
if (self.inner_action && self.inner_action.get_action_descr().id) {
self.webclient.menu.open_action(self.inner_action.get_action_descr().id);
}
});
});
}
}
} else if (state.model && state.id) {
@@ -524,9 +529,9 @@ var ActionManager = Widget.extend({
});
}
$.when(action_loaded || null).done(function() {
return $.when(action_loaded || null).done(function() {
if (self.inner_widget && self.inner_widget.do_load_state) {
self.inner_widget.do_load_state(state, warm);
return self.inner_widget.do_load_state(state, warm);
}
});
},
@@ -628,7 +633,9 @@ var ActionManager = Widget.extend({
});
}
return this[type](action, options);
return $.when(this[type](action, options)).then(function() {
return action;
});
},
null_action: function() {
this.dialog_stop();
@@ -645,6 +652,7 @@ var ActionManager = Widget.extend({
* @return {*}
*/
ir_actions_common: function(executor, options) {
var self = this;
if (executor.action.target === 'new') {
var pre_dialog = (this.dialog && !this.dialog.isDestroyed()) ? this.dialog : null;
if (pre_dialog){
@@ -693,13 +701,16 @@ var ActionManager = Widget.extend({
this.dialog_widget.set_cp_bus(new core.Bus());
}
this.dialog_widget.setParent(this.dialog);
this.dialog.open();
return this.dialog_widget.appendTo(this.dialog.$el);
var fragment = document.createDocumentFragment();
return this.dialog_widget.appendTo(fragment).then(function() {
self.dialog.open().$el.append(fragment);
if(options.state && self.dialog_widget.do_load_state) {
return self.dialog_widget.do_load_state(options.state);
}
}).then(function () { return executor.action; });
}
// Clear uncommitted changes on the current inner widget if there is one
var self = this;
var def = (this.inner_widget && this.webclient.clear_uncommitted_changes()) || $.when();
var def = this.inner_action && this.webclient && this.webclient.clear_uncommitted_changes() || $.when();
return def.then(function() {
self.dialog_stop(executor.action);
return self.push_action(executor.widget(), executor.action, options);
@@ -764,11 +775,11 @@ var ActionManager = Widget.extend({
},
ir_actions_server: function (action, options) {
var self = this;
this.rpc('/web/action/run', {
return this.rpc('/web/action/run', {
action_id: action.id,
context: action.context || {}
}).done(function (action) {
self.do_action(action, options);
}).then(function (action) {
return self.do_action(action, options);
});
},
ir_actions_report_xml: function(action, options) {
@@ -818,6 +829,7 @@ var ActionManager = Widget.extend({
if (action.target === 'self') {
framework.redirect(url);
return $.Deferred(); // The action is finished only when the redirection is done
} else {
window.open(url, '_blank');
}
+90 -83
View File
@@ -1,4 +1,4 @@
odoo.define('base.apps', function (require) {
odoo.define('web.Apps', function (require) {
"use strict";
var core = require('web.core');
@@ -9,10 +9,9 @@ var web_client = require('web.web_client');
var Widget = require('web.Widget');
var _t = core._t;
var qweb = core.qweb;
var apps_client = null;
var qweb = core.qweb;
var Apps = Widget.extend({
template: 'EmptyComponent',
@@ -106,92 +105,98 @@ var Apps = Widget.extend({
}
},
_on_update_count: function(m) {
var self = this;
var count = m.count;
var get_upd_menu_id = function() {
if (_.isUndefined(self._upd_menu_id)) {
var IMD = new Model('ir.model.data');
return IMD.call('get_object_reference', ['base', 'menu_module_updates']).then(function(r) {
var mid = r[1];
if(r[0] !== 'ir.ui.menu') {
// invalid reference, return null
mid = null;
}
self._upd_menu_id = mid;
return mid;
});
} else {
return $.Deferred().resolve(self._upd_menu_id).promise();
}
};
$.when(get_upd_menu_id()).done(function(menu_id) {
if (_.isNull(menu_id)) {
return;
}
var $menu = web_client.menu.$secondary_menus.find(_.str.sprintf('a[data-menu=%s]', menu_id));
if ($menu.length === 0) {
return;
}
if (_.isUndefined(count)) {
count = 0;
}
var needupdate = $menu.find('#menu_counter');
if (needupdate && needupdate.length !== 0) {
if (count > 0) {
needupdate.text(count);
} else {
needupdate.remove();
}
} else if (count > 0) {
$menu.append(qweb.render("Menu.needaction_counter", {widget: {needaction_counter: count}}));
}
});
},
start: function() {
var self = this;
return self.get_client().
done(function(client) {
self.client = client;
var def = $.Deferred();
self.get_client().then(function(client) {
self.client = client;
var qs = (session.debug ? 'debug&' : '') + 'db=' + client.dbname;
var u = client.origin + '/apps/embed/client?' + qs;
var css = {width: '100%', height: '400px'};
self.$ifr = $('<iframe>').attr('src', u);
var qs = (session.debug ? 'debug&' : '') + 'db=' + client.dbname;
var u = client.origin + '/apps/embed/client?' + qs;
var css = {width: '100%', height: '400px'};
self.$ifr = $('<iframe>').attr('src', u);
$(window).on("message.apps", self.proxy('_on_message'));
$(window).on("message.apps", self.proxy('_on_message'));
self.on('message:ready', self, function(m) {
var w = this.$ifr[0].contentWindow;
var act = {
type: 'ir.actions.client',
tag: this.remote_action_tag,
params: _.extend({}, this.params, {
db: this.session.db,
origin: this.session.origin,
})
};
w.postMessage({type:'action', action: act}, client.origin);
});
self.on('message:set_height', self, function(m) {
this.$ifr.height(m.height);
});
self.on('message:update_count', self, function(m) {
var count = m.count;
var get_upd_menu_id = function() {
if (_.isUndefined(self._upd_menu_id)) {
var IMD = new Model('ir.model.data');
return IMD.call('get_object_reference', ['base', 'menu_module_updates']).then(function(r) {
var mid = r[1];
if(r[0] !== 'ir.ui.menu') {
// invalid reference, return null
mid = null;
}
self._upd_menu_id = mid;
return mid;
});
} else {
return $.Deferred().resolve(self._upd_menu_id).promise();
}
};
$.when(get_upd_menu_id()).done(function(menu_id) {
if (_.isNull(menu_id)) {
return;
}
var $menu = web_client.menu.$secondary_menus.find(_.str.sprintf('a[data-menu=%s]', menu_id));
if ($menu.length === 0) {
return;
}
if (_.isUndefined(count)) {
count = 0;
}
var needupdate = $menu.find('#menu_counter');
if (needupdate && needupdate.length !== 0) {
if (count > 0) {
needupdate.text(count);
} else {
needupdate.remove();
}
} else if (count > 0) {
$menu.append(qweb.render("Menu.needaction_counter", {widget: {needaction_counter: count}}));
}
});
});
self.on('message:blockUI', self, function() { framework.blockUI(); });
self.on('message:unblockUI', self, function() { framework.unblockUI(); });
self.on('message:warn', self, function(m) {self.do_warn(m.title, m.message, m.sticky); });
self.$ifr.appendTo(self.$el).css(css).addClass('apps-client');
}).
fail(function(client) {
self.do_warn(_t('Odoo Apps will be available soon'), _t('Showing locally available modules'), true);
self.rpc('/web/action/load', {action_id: self.failback_action_id}).done(function(action) {
self.do_action(action);
web_client.menu.open_action(action.id);
});
self.on('message:ready', self, function(m) {
var w = this.$ifr[0].contentWindow;
var act = {
type: 'ir.actions.client',
tag: this.remote_action_tag,
params: _.extend({}, this.params, {
db: this.session.db,
origin: this.session.origin,
})
};
w.postMessage({type:'action', action: act}, client.origin);
});
self.on('message:set_height', self, function(m) {
this.$ifr.height(m.height);
});
self.on('message:update_count', self, self._on_update_count);
self.on('message:blockUI', self, function() { framework.blockUI(); });
self.on('message:unblockUI', self, function() { framework.unblockUI(); });
self.on('message:warn', self, function(m) {self.do_warn(m.title, m.message, m.sticky); });
self.$ifr.appendTo(self.$el).css(css).addClass('apps-client');
def.resolve();
}, function() {
self.do_warn(_t('Odoo Apps will be available soon'), _t('Showing locally available modules'), true);
return session.rpc('/web/action/load', {action_id: self.failback_action_id}).then(function(action) {
return self.do_action(action);
}).always(function () {
def.reject();
});
});
return def;
},
});
@@ -202,4 +207,6 @@ var AppsUpdates = Apps.extend({
core.action_registry.add("apps", Apps);
core.action_registry.add("apps.updates", AppsUpdates);
return Apps;
});
-1
View File
@@ -199,7 +199,6 @@
process_jobs: function (jobs, services) {
var job;
var require;
var time;
function process_job (job) {
var require = make_require(job);
+1 -3
View File
@@ -22,7 +22,6 @@ var form_relational = require('web.form_relational'); // necessary
var form_widgets = require('web.form_widgets'); // necessary
var framework = require('web.framework');
var ListView = require('web.ListView');
var Menu = require('web.Menu');
var Model = require('web.DataModel');
var pyeval = require('web.pyeval');
var Registry = require('web.Registry');
@@ -96,7 +95,6 @@ openerp.web.FormView = FormView;
openerp.web.json_node_to_xml = utils.json_node_to_xml;
openerp.web.ListView = ListView;
openerp.web.Menu = Menu;
openerp.web.Model = Model;
openerp.web.normalize_format = time.strftime_to_moment_format;
openerp.web.py_eval = pyeval.py_eval;
@@ -208,7 +206,7 @@ ListView.include({
}).value();
}
return this._super(data);
return this._super();
},
/**
* Returns the style for the provided record in the current view (from the
+27 -24
View File
@@ -54,17 +54,15 @@ var ControlPanel = Widget.extend({
* @return {jQuery.Deferred}
*/
start: function() {
this.$title_col = this.$('.oe-cp-title');
// Exposed jQuery nodesets
this.nodes = {
$breadcrumbs: this.$('.oe-view-title'),
$buttons: this.$('.oe-cp-buttons'),
$pager: this.$('.oe-cp-pager'),
$searchview: this.$('.oe-cp-search-view'),
$searchview_buttons: this.$('.oe-search-options'),
$sidebar: this.$('.oe-cp-sidebar'),
$switch_buttons: this.$('.oe-cp-switch-buttons'),
$breadcrumbs: this.$('.breadcrumb'),
$buttons: this.$('.o_cp_buttons'),
$pager: this.$('.o_cp_pager'),
$searchview: this.$('.o_cp_searchview'),
$searchview_buttons: this.$('.o_search_options'),
$sidebar: this.$('.o_cp_sidebar'),
$switch_buttons: this.$('.o_cp_switch_buttons'),
};
// By default, hide the ControlPanel and remove its contents from the DOM
@@ -120,7 +118,7 @@ var ControlPanel = Widget.extend({
// Update the searchview and switch buttons
this._update_search_view(status.searchview, status.search_view_hidden);
if (status.active_view_selector) {
if (status.active_view_selector) {
this._update_switch_buttons(status.active_view_selector);
}
}
@@ -182,22 +180,25 @@ var ControlPanel = Widget.extend({
*/
_render_breadcrumbs: function (breadcrumbs) {
var self = this;
return breadcrumbs.map(function (bc, index) {
return make_breadcrumb(bc, index === breadcrumbs.length - 1);
return self._render_breadcrumbs_li(bc, index, breadcrumbs.length);
});
function make_breadcrumb (bc, is_last) {
var $bc = $('<li>')
.append(is_last ? _.escape(bc.title) : $('<a>').text(bc.title))
.toggleClass('active', is_last);
if (!is_last) {
$bc.click(function () {
self.trigger("on_breadcrumb_click", bc.action, bc.index);
});
}
return $bc;
},
/**
* Private function that renders a breadcrumbs' li Jquery element
*/
_render_breadcrumbs_li: function (bc, index, length) {
var self = this;
var is_last = (index === length-1);
var $bc = $('<li>')
.append(is_last ? _.escape(bc.title) : $('<a>').text(bc.title))
.toggleClass('active', is_last);
if (!is_last) {
$bc.click(function () {
self.trigger("on_breadcrumb_click", bc.action, bc.index);
});
}
return $bc;
},
/**
* Private function that updates the SearchView's visibility and extend the
@@ -211,8 +212,10 @@ var ControlPanel = Widget.extend({
// have been appended to a jQuery node not in the DOM at SearchView initialization
searchview.$buttons = this.nodes.$searchview_buttons;
searchview.toggle_visibility(!is_hidden);
this.$title_col.toggleClass('col-md-6', !is_hidden).toggleClass('col-md-12', is_hidden);
}
this.nodes.$searchview.toggle(!is_hidden);
this.$el.toggleClass('o_breadcrumb_full', !!is_hidden);
},
});
+8 -9
View File
@@ -2,8 +2,8 @@ odoo.define('web.ajax', function (require) {
"use strict";
var core = require('web.core');
var time = require('web.time');
var utils = require('web.utils');
var time = require('web.time');
function genericJsonRpc (fct_name, params, fct) {
var data = {
@@ -14,6 +14,7 @@ function genericJsonRpc (fct_name, params, fct) {
};
var xhr = fct(data);
var result = xhr.pipe(function(result) {
core.bus.trigger('rpc:result', data, result);
if (result.error !== undefined) {
if (result.error.data.arguments[0] !== "bus.Bus not available in test mode") {
console.error("Server application error", JSON.stringify(result.error));
@@ -42,7 +43,7 @@ function jsonRpc(url, fct_name, params, settings) {
contentType: 'application/json'
}));
});
};
}
function jsonpRpc(url, fct_name, params, settings) {
settings = settings || {};
@@ -116,7 +117,7 @@ function jsonpRpc(url, fct_name, params, settings) {
return deferred;
}
});
};
}
// helper
function realSetTimeout (fct, millis) {
@@ -140,7 +141,7 @@ function loadCSS(url) {
'type': 'text/css'
}));
}
};
}
function loadJS(url) {
var def = $.Deferred();
@@ -165,7 +166,7 @@ function loadJS(url) {
head.appendChild(script);
}
return def;
};
}
/**
* Cooperative file download implementation, for ajaxy APIs.
@@ -301,7 +302,7 @@ function post (controller_url, data) {
var Def = $.Deferred();
var postData = new FormData();
$.each(data, function(i,val) {
postData.append(i, val);
});
@@ -311,7 +312,7 @@ function post (controller_url, data) {
var xhr = new XMLHttpRequest();
if(xhr.upload) xhr.upload.addEventListener('progress', progressHandler(Def), false);
var ajaxDef = $.ajax(controller_url, {
xhr: function() {return xhr;},
data: postData,
@@ -324,8 +325,6 @@ function post (controller_url, data) {
return Def;
}
var loadXML = (function () {
var loading = false;
var urls = [];
+6 -10
View File
@@ -177,20 +177,16 @@ return {
_lt: _lt,
// registries
view_registry: new Registry(),
crash_registry: new Registry(),
action_registry : new Registry(),
form_widget_registry: new Registry(),
form_tag_registry: new Registry(),
crash_registry: new Registry(),
form_custom_registry: new Registry(),
form_tag_registry: new Registry(),
form_widget_registry: new Registry(),
list_widget_registry: new Registry(),
search_widgets_registry: new Registry(),
search_filters_registry: new Registry(),
// necessary to make the kanban view compatible between
// community and enterprise edition
one2many_view_registry: new Registry(),
search_filters_registry: new Registry(),
search_widgets_registry: new Registry(),
view_registry: new Registry(),
};
@@ -40,22 +40,17 @@ var CrashManager = core.Class.extend({
if (!this.active) {
return;
}
if (this.$indicator){
if (this.connection_lost) {
return;
}
if (error.code == -32098) {
$.blockUI({ message: '' , overlayCSS: {'z-index': 9999, backgroundColor: '#FFFFFF', opacity: 0.0, cursor: 'wait'}});
this.$indicator = $('<div class="oe_indicator">' + _t("Trying to reconnect... ") + '<i class="fa fa-refresh"></i></div>');
this.$indicator.prependTo("body");
var timeinterval = setInterval(function(){
core.bus.trigger('connection_lost');
this.connection_lost = true;
var timeinterval = setInterval(function() {
ajax.jsonRpc('/web/webclient/version_info').then(function() {
clearInterval(timeinterval);
self.$indicator.html(_t("You are back online"));
self.$indicator.delay(2000).fadeOut('slow',function(){
$(this).remove();
self.$indicator.remove();
});
$.unblockUI();
core.bus.trigger('connection_restored');
self.connection_lost = false;
});
}, 2000);
return;
+4 -8
View File
@@ -320,6 +320,7 @@ var DataSet = Class.extend(mixins.PropertiesMixin, {
this.index = null;
this._sort = [];
this._model = new Model(model, context);
this.orderer = new utils.DropMisordered();
},
previous: function () {
this.index -= 1;
@@ -408,10 +409,11 @@ var DataSet = Class.extend(mixins.PropertiesMixin, {
read_slice: function (fields, options) {
var self = this;
options = options || {};
return this._model.query(fields)
var query = this._model.query(fields)
.limit(options.limit || false)
.offset(options.offset || 0)
.all().done(function (records) {
.all();
return this.orderer.add(query).done(function (records) {
self.ids = _(records).pluck('id');
});
},
@@ -761,12 +763,6 @@ var BufferedDataSet = DataSetStatic.extend({
_.extend(cached.from_read, options.from_read);
_.extend(cached.changes, options.changes);
_.extend(cached.readonly_fields, options.readonly_fields);
// discard values from cached.changes that are in cached.from_read
_.each(cached.changes, function (v, k) {
if (cached.from_read[k] === v) {
delete cached.changes[k];
}
});
if (options.to_create !== undefined) cached.to_create = options.to_create;
if (options.to_delete !== undefined) cached.to_delete = options.to_delete;
}
+54 -10
View File
@@ -211,6 +211,16 @@ if ('nv' in window) {
nv.tooltip.cleanup = function () {
$('.nvtooltip').remove();
};
// monkey patch nvd3 to prevent it to display a tooltip (position: absolute) with
// a negative `top`; with this patch the highest tooltip's position is still in the
// graph
var originalCalcTooltipPosition = nv.tooltip.calcTooltipPosition;
nv.tooltip.calcTooltipPosition = function () {
var container = originalCalcTooltipPosition.apply(this, arguments);
container.style.top = container.style.top.split('px')[0] < 0 ? 0 + 'px' : container.style.top;
return container;
};
}
// Bootstrap customization
@@ -303,11 +313,18 @@ $.extend( proto, {
});
/**
* Private function that triggers an event on core.bus
* Private function to notify that something has been attached in the DOM
* @param {htmlString or Element or Array or jQuery} [content] the content that
* has been attached in the DOM
* @params {Array} [callbacks] array of {widget: w, callback_args: args} such
* that on_attach_callback() will be called on each w with arguments args
*/
function _notify (content) {
function _notify (content, callbacks) {
_.each(callbacks, function(c) {
if (c.widget && c.widget.on_attach_callback) {
c.widget.on_attach_callback(c.callback_args);
}
});
core.bus.trigger('DOM_updated', content);
}
/**
@@ -315,12 +332,14 @@ function _notify (content) {
* @param {jQuery} [$target] the node where content will be appended
* @param {htmlString or Element or Array or jQuery} [content] DOM element,
* array of elements, HTML string or jQuery object to append to $target
* @param {jQuery} [trigger] true to trigger an event, false otherwise
* @param {Boolean} [options.in_DOM] true if $target is in the DOM
* @param {Array} [options.callbacks] array of objects describing the callbacks
* to perform (see _notify for a complete description)
*/
function append ($target, content, trigger) {
function append ($target, content, options) {
$target.append(content);
if (trigger) {
_notify(content);
if (options && options.in_DOM) {
_notify(content, options.callbacks);
}
}
/**
@@ -328,15 +347,39 @@ function append ($target, content, trigger) {
* @param {jQuery} [$target] the node where content will be prepended
* @param {htmlString or Element or Array or jQuery} [content] DOM element,
* array of elements, HTML string or jQuery object to prepend to $target
* @param {jQuery} [trigger] true to trigger an event, false otherwise
* @param {Boolean} [options.in_DOM] true if $target is in the DOM
* @param {Array} [options.callbacks] array of objects describing the callbacks
* to perform (see _notify for a complete description)
*/
function prepend ($target, content, trigger) {
function prepend ($target, content, options) {
$target.prepend(content);
if (trigger) {
_notify(content);
if (options && options.in_DOM) {
_notify(content, options.callbacks);
}
}
/**
* Detaches widgets from the DOM and performs their on_detach_callback()
* @param {Array} [to_detach] array of {widget: w, callback_args: args} such
* that w.$el will be detached and w.on_detach_callback(args) will be called
* @param {jQuery} [options.$to_detach] if given, detached instead of widgets' $el
* @return {jQuery} the detached elements
*/
function detach (to_detach, options) {
_.each(to_detach, function(d) {
if (d.widget.on_detach_callback) {
d.widget.on_detach_callback(d.callback_args);
}
});
var $to_detach = options && options.$to_detach;
if (!$to_detach) {
$to_detach = $(_.map(to_detach, function(d) {
return d.widget.el;
}));
}
return $to_detach.detach();
}
/**
* Returns the distance between a DOM element and the top-left corner of the window
* @param {element} [e] the DOM element
@@ -358,6 +401,7 @@ return {
redirect: redirect,
append: append,
prepend: prepend,
detach: detach,
getPosition: getPosition,
};
+2 -4
View File
@@ -6,14 +6,12 @@ var session = require('web.session');
var Model = Class.extend({
/**
new openerp.web.Model([session,] model_name[, context[, domain]])
new openerp.web.Model(name[, context[, domain]])
@constructs instance.web.Model
@extends instance.web.Class
@param {openerp.web.Session} [session] The session object used to communicate with
the server.
@param {String} model_name name of the OpenERP model this object is bound to
@param {String} name name of the OpenERP model this object is bound to
@param {Object} [context]
@param {Array} [domain]
*/
@@ -236,7 +236,7 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
return d;
},
load_qweb: function(mods) {
this.qweb_mutex.exec(function() {
this.qweb_mutex.exec(function () {
return $.get('/web/webclient/qweb?mods=' + mods).then(function (doc) {
if (!doc) { return; }
qweb.add_template(doc);
@@ -423,7 +423,6 @@ function swap(array, elem1, elem2) {
array[i1] = elem2;
}
return {
divmod: divmod,
modf: modf,
+19 -17
View File
@@ -27,6 +27,8 @@ var View = Widget.extend({
// multi_record is used to distinguish views displaying a single record
// (e.g. FormView) from those that display several records (e.g. ListView)
multi_record: true,
// indicates whether or not the view is mobile-friendly
mobile_friendly: false,
// icon is the font-awesome icon to display in the view switcher
icon: 'fa-question',
// whether or not the view requires the model's fields to render itself
@@ -45,11 +47,8 @@ var View = Widget.extend({
* @return {Deferred}
*/
start: function() {
// add css classes that reflect the (absence of) access rights
this.$el.addClass('oe_view')
.toggleClass('oe_cannot_create', !this.is_action_enabled('create'))
.toggleClass('oe_cannot_edit', !this.is_action_enabled('edit'))
.toggleClass('oe_cannot_delete', !this.is_action_enabled('delete'));
// add classname that reflect the (absence of) access rights
this.$el.toggleClass('o_cannot_create', !this.is_action_enabled('create'));
return this._super().then(this.trigger.bind(this, 'view_loaded'));
},
/**
@@ -76,7 +75,7 @@ var View = Widget.extend({
// response handler
var handler = function (action) {
if (action && action.constructor == Object) {
if (action && action.constructor === Object) {
// filter out context keys that are specific to the current action.
// Wrong default_* and search_default_* values will no give the expected result
// Wrong group_by values will simply fail and forbid rendering of the destination view
@@ -106,7 +105,7 @@ var View = Widget.extend({
if (action_data.special === 'cancel') {
return handler({"type":"ir.actions.act_window_close"});
} else if (action_data.type=="object") {
} else if (action_data.type === "object") {
var args = [[record_id]];
if (action_data.args) {
try {
@@ -122,7 +121,7 @@ var View = Widget.extend({
return dataset.call_button(action_data.name, args).then(handler).then(function () {
core.bus.trigger('do_reload_needaction');
});
} else if (action_data.type=="action") {
} else if (action_data.type === "action") {
return data_manager.load_action(action_data.name, _.extend(pyeval.eval('context', context), {
active_model: dataset.model,
active_ids: dataset.ids,
@@ -144,27 +143,24 @@ var View = Widget.extend({
do_load_state: function (state, warm) {
},
/**
* This function should render the buttons of the view, set this.$buttons to
* the produced jQuery element and define some listeners on it.
* This function should be called after start().
* This function should render the action buttons of the view.
* It should be called after start().
* @param {jQuery} [$node] a jQuery node where the rendered buttons should be inserted
* $node may be undefined, in which case the View can insert the buttons somewhere else
*/
render_buttons: function($node) {
},
/**
* This function should instantiate and render the sidebar of the view, set this.sidebar to
* the instantiated Sidebar Widget and possibly add custom items in it.
* This function should be called after start().
* This function should render the sidebar of the view.
* It should be called after start().
* @param {jQuery} [$node] a jQuery node where the sidebar should be inserted
* $node may be undefined, in which case the View can insert the sidebar somewhere else
*/
render_sidebar: function($node) {
},
/**
* This function should render the pager of the view, set this.$pager to
* the produced jQuery element and define some listeners on it.
* This function should be called after start().
* This function should render the pager of the view.
* It should be called after start().
* @param {jQuery} [$node] a jQuery node where the pager should be inserted
* $node may be undefined, in which case the View can insert the pager somewhere else
*/
@@ -200,6 +196,12 @@ var View = Widget.extend({
get_context: function () {
return {};
},
set_scrollTop: function(scrollTop) {
this.scrollTop = scrollTop;
},
get_scrollTop: function() {
return this.scrollTop;
}
});
return View;
+1 -1
View File
@@ -32,7 +32,7 @@ var mixins = core.mixins;
* },
* start: function() {
* // stuff you want to make after the rendering, `this.$el` holds a correct value
* this.$el.find(".my_button").click(/* an example of event binding * /);
* this.$(".my_button").click(/* an example of event binding * /);
*
* // if you have some asynchronous operations, it's a good idea to return
* // a promise in start()
+3 -3
View File
@@ -15,7 +15,7 @@ var Menu = Widget.extend({
this.data = {data:{children:[]}};
this.on("menu_bound", this, function() {
// launch the fetch of needaction counters, asynchronous
var $all_menus = self.$el.parents('body').find('.oe_webclient').find('[data-menu]');
var $all_menus = self.$el.parents('.o_web_client').find('.o_sub_menu').find('[data-menu]');
var all_menu_ids = _.map($all_menus, function (menu) {return parseInt($(menu).attr('data-menu'), 10);});
if (!_.isEmpty(all_menu_ids)) {
this.do_load_needaction(all_menu_ids);
@@ -34,7 +34,7 @@ var Menu = Widget.extend({
},
bind_menu: function() {
var self = this;
this.$secondary_menus = this.$el.parents().find('.oe_secondary_menus_container');
this.$secondary_menus = this.$el.parents().find('.o_sub_menu');
this.$secondary_menus.on('click', 'a[data-menu]', this.on_menu_click);
this.$el.on('click', 'a[data-menu]', function (event) {
event.preventDefault();
@@ -160,7 +160,7 @@ var Menu = Widget.extend({
$sub_menu.show();
// Hide/Show the leftbar menu depending of the presence of sub-items
this.$secondary_menus.parent('.oe_leftbar').toggle(!!$sub_menu.children().length);
this.$secondary_menus.toggle(!!$sub_menu.children().length);
// Activate current menu item and show parents
this.$secondary_menus.find('.active').removeClass('active');

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