summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorAntoine Huvelle <ahu@openerp.com>2011-12-16 14:07:41 +0100
committerAntoine Huvelle <ahu@openerp.com>2011-12-16 14:07:41 +0100
commit4bbb1c06833d83df5c8f3dc1469030462a83c5bd (patch)
tree85f3a5184ea8a18f2cd5c21423c0e452ad694a2e /addons/web/static/src
parent5026c6b43ec6b9490a708c2fc7370d96664a84dc (diff)
parent2989c829f760df5bc182510146d67fdf9a877908 (diff)
[IMP] changes in 'group by' padding
bzr revid: ahu@openerp.com-20111216083515-tvmyyn1zzh34qzfp bzr revid: ahu@openerp.com-20111216130741-a6f0bv7ixq16osg6
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/css/base.css153
-rw-r--r--addons/web/static/src/img/pencil.gifbin0 -> 129 bytes
-rw-r--r--addons/web/static/src/js/chrome.js209
-rw-r--r--addons/web/static/src/js/core.js317
-rw-r--r--addons/web/static/src/js/data.js9
-rw-r--r--addons/web/static/src/js/data_export.js17
-rw-r--r--addons/web/static/src/js/data_import.js8
-rw-r--r--addons/web/static/src/js/formats.js2
-rw-r--r--addons/web/static/src/js/view_editor.js155
-rw-r--r--addons/web/static/src/js/view_form.js70
-rw-r--r--addons/web/static/src/js/view_list.js56
-rw-r--r--addons/web/static/src/js/view_list_editable.js7
-rw-r--r--addons/web/static/src/js/view_page.js25
-rw-r--r--addons/web/static/src/js/view_tree.js7
-rw-r--r--addons/web/static/src/js/views.js144
-rw-r--r--addons/web/static/src/xml/base.xml77
16 files changed, 772 insertions, 484 deletions
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css
index 7dec0c49775..8bd2c61d94b 100644
--- a/addons/web/static/src/css/base.css
+++ b/addons/web/static/src/css/base.css
@@ -2,7 +2,6 @@ body.openerp {
padding: 0;
margin: 0;
height: 100%;
- min-width: 1000px;
overflow-y: scroll;
font-size: 80%;
font-family: Ubuntu, Helvetica, sans-serif;
@@ -363,7 +362,7 @@ label.error {
position: absolute;
z-index: 100;
border: 4px solid #585858;
- border: 4px solid rgba(88, 88, 88, .5);
+ border-color: rgba(88, 88, 88, .5);
border-radius: 4px;
min-width: 200px;
}
@@ -609,6 +608,10 @@ label.error {
}
.openerp .filter_label.enabled, .openerp .filter_icon.enabled {
background: #aaa;
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ -o-box-shadow: none;
+ box-shadow: none;
}
.openerp .filter_icon {
height: 22px;
@@ -631,6 +634,13 @@ label.error {
padding-right: 0.4em;
white-space: nowrap;
}
+
+.openerp .filter_label_group button {
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+ border-right: none;
+}
.openerp .filter_label_group button:first-child {
-webkit-border-top-left-radius: 7px;
-webkit-border-bottom-left-radius: 7px;
@@ -640,9 +650,6 @@ label.error {
border-bottom-left-radius: 7px;
border-right: none;
}
-.openerp .filter_label_group button {
- border-right: none;
-}
.openerp .filter_label_group button:last-child {
-webkit-border-top-right-radius: 7px;
-webkit-border-bottom-right-radius: 7px;
@@ -658,12 +665,12 @@ label.error {
.openerp .filter_label_group button.filter_icon:first-child {
border-left: solid 1px #999;
margin-left: -7px;
- -webkit-border-top-left-radius: 0px;
- -webkit-border-bottom-left-radius: 0px;
- -moz-border-radius-topleft: 0px;
- -moz-border-radius-bottomleft: 0px;
- border-top-left-radius: 0px;
- border-bottom-left-radius: 0px;
+ -webkit-border-top-left-radius: 0;
+ -webkit-border-bottom-left-radius: 0;
+ -moz-border-radius-topleft: 0;
+ -moz-border-radius-bottomleft: 0;
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
}
.openerp .searchview_group_string {
@@ -671,7 +678,6 @@ label.error {
color: #7D7979;
font-weight: bold;
padding: 2px 0 2px 10px;
- margin-top: 4px;
text-decoration: none;
}
.openerp .searchview_group_string:hover {
@@ -688,6 +694,7 @@ label.error {
}
.openerp .searchview_group.expanded .searchview_group_content {
display: block;
+ padding-bottom:3px;
}
.openerp .searchview_group_content .oe_label, .openerp .searchview_group_content .oe_label_help {
@@ -724,7 +731,7 @@ label.error {
}
.openerp .oe_search-view-buttons {
- padding: 10px 0 10px 0;
+ padding: 2px 0 10px 0;
vertical-align:middle;
}
.openerp .oe_search-view-filters-management {
@@ -836,13 +843,17 @@ label.error {
border-bottom: 1px solid #E3E3E3;
}
+
.openerp .oe-listview td.oe-actions {
border-bottom:none;
}
-.openerp .oe-listview .oe-record-selector {
+.openerp .oe-listview .oe-record-selector, .openerp .oe-listview .oe-record-edit-link {
border-bottom: 1px solid #E3E3E3;
}
+.openerp .oe-listview .oe-record-edit-link {
+ cursor: pointer;
+}
.openerp .oe-listview .oe-field-cell {
cursor: pointer;
@@ -994,15 +1005,13 @@ label.error {
.openerp .field_date,
.openerp .field_float,
.openerp .field_selection,
-.openerp .oe_form_field_many2one a,
-.openerp .oe_form_field_reference a{
+.openerp a.oe_form_uri {
vertical-align: middle;
padding-top: 3px;
font-size: 90%;
color: #222;
}
-.openerp .oe_form_field_many2one a,
-.openerp .oe_form_field_reference a {
+.openerp a.oe_form_uri {
color: #9A0404;
line-height: 12px;
}
@@ -1013,7 +1022,7 @@ label.error {
.openerp .oe_form_frame_cell input[type="checkbox"] {
margin-top: 3px;
- vertical-align: center;
+ vertical-align: middle;
}
.openerp .oe_form_frame_cell .input[type="text"] {
padding-bottom: 1px;
@@ -1242,7 +1251,7 @@ label.error {
.openerp .oe_datepicker_root {
display: inline-block;
}
-.openerp .oe_forms.oe_frame .oe_datepicker_root {
+.openerp .oe_form_frame_cell .oe_datepicker_root {
width: 100%;
}
.openerp .oe_input_icon_disabled {
@@ -1569,6 +1578,10 @@ label.error {
.openerp.kitten-mode-activated .main_table {
background: url(http://placekitten.com/g/1500/800) repeat;
}
+.openerp.kitten-mode-activated.clark-gable .main_table {
+ background: url(http://amigrave.com/ClarkGable.jpg);
+ background-size: 100%;
+}
.openerp.kitten-mode-activated .header {
background: url(http://placekitten.com/g/211/65) repeat;
@@ -1745,9 +1758,7 @@ ul.oe-arrow-list li {
ul.oe-arrow-list li span {
vertical-align: top;
display: inline-block;
- border-width:1em;
- border-style:solid;
- border-color: #DEDEDE;
+ border: 1em solid #DEDEDE;
line-height:0em;
}
ul.oe-arrow-list .oe-arrow-list-before {
@@ -1910,3 +1921,99 @@ ul.oe-arrow-list li.oe-arrow-list-selected .oe-arrow-list-after {
background: url("/web/static/src/img/pager_last.png") no-repeat scroll center center transparent;
}
+/* Buttons */
+.openerp a.button:link,
+.openerp a.button:visited,
+.openerp button {
+ display: inline-block;
+ border: 1px solid #ababab;
+ color: #404040;
+ font-size: 12px;
+ padding: 3px 10px;
+ text-align: center;
+ -o-background-size: 100% 100%;
+ -moz-background-size: 100% 100%;
+ -webkit-background-size: auto auto !important;
+ background-size: 100% 100%;
+ background: #d8d8d8 none;
+ background: none, -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#d8d8d8));
+ background: none, -webkit-linear-gradient(#efefef, #d8d8d8);
+ background: none, -moz-linear-gradient(#efefef, #d8d8d8);
+ background: none, -o-linear-gradient(top, #efefef, #d8d8d8);
+ background: none, -khtml-gradient(linear, left top, left bottom, from(#efefef), to(#d8d8d8));
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ -o-border-radius: 3px;
+ -ms-border-radius: 3px;
+ border-radius: 3px;
+ -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
+ -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+ -webkit-font-smoothing: antialiased;
+ outline: none;
+}
+
+.openerp a.button:hover,
+.openerp button:hover {
+ -o-background-size: 100% 100%;
+ -moz-background-size: 100% 100%;
+ -webkit-background-size: auto auto !important;
+ background-size: 100% 100%;
+ background: #e3e3e3 none;
+ background: none, -webkit-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e3e3e3));
+ background: none, -webkit-linear-gradient(#f6f6f6, #e3e3e3);
+ background: none, -moz-linear-gradient(#f6f6f6, #e3e3e3);
+ background: none, -o-linear-gradient(top, #f6f6f6, #e3e3e3);
+ background: none, -khtml-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e3e3e3));
+ cursor: pointer;
+}
+
+.openerp a.button:focus,
+.openerp button:focus {
+ border: 1px solid #80bfff;
+ -o-background-size: 100% 100%;
+ -moz-background-size: 100% 100%;
+ -webkit-background-size: auto auto !important;
+ background-size: 100% 100%;
+ background: #e3e3e3, none;
+ background: none, -webkit-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e3e3e3));
+ background: none, -webkit-linear-gradient(#f6f6f6, #e3e3e3);
+ background: none, -moz-linear-gradient(#f6f6f6, #e3e3e3);
+ background: none, -o-linear-gradient(top, #f6f6f6, #e3e3e3);
+ background: none, -khtml-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e3e3e3));
+ -moz-box-shadow: 0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, 0.8) inset;
+ -webkit-box-shadow: 0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, 0.8) inset;
+ -o-box-shadow: 0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, 0.8) inset;
+ box-shadow: 0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, 0.8) inset;
+}
+
+.openerp a.button:active,
+.openerp a.button.active,
+.openerp button:active,
+.openerp button.active {
+ background: #e3e3e3;
+ background: -moz-linear-gradient(top, #e3e3e3, #f6f6f6) #1b468f;
+ background: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f6f6f6)) #1b468f;
+ background: linear-gradient(top, #e3e3e3, #f6f6f6) #1b468f;
+ -moz-box-shadow: none, 0 0 0 transparent;
+ -webkit-box-shadow: none, 0 0 0 transparent;
+ -o-box-shadow: none, 0 0 0 transparent;
+ box-shadow: none, 0 0 0 transparent;
+}
+
+.openerp a.button.disabled,
+.openerp button:disabled {
+ background: #efefef !important;
+ border: 1px solid #d1d1d1 !important;
+ font-size: 12px;
+ padding: 3px 10px;
+ -moz-box-shadow: none !important, 0 0 0 transparent;
+ -webkit-box-shadow: none !important, 0 0 0 transparent;
+ -o-box-shadow: none !important, 0 0 0 transparent;
+ box-shadow: none !important, 0 0 0 transparent;
+ color: #aaaaaa !important;
+ cursor: default;
+ text-shadow: 0 1px 1px white !important;
+}
diff --git a/addons/web/static/src/img/pencil.gif b/addons/web/static/src/img/pencil.gif
new file mode 100644
index 00000000000..6e9aa5ef659
--- /dev/null
+++ b/addons/web/static/src/img/pencil.gif
Binary files differ
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index 83f7f971434..50fb8018918 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -2,7 +2,8 @@
* OpenERP Web chrome
*---------------------------------------------------------*/
openerp.web.chrome = function(openerp) {
-var QWeb = openerp.web.qweb;
+var QWeb = openerp.web.qweb,
+ _t = openerp.web._t;
openerp.web.Notification = openerp.web.Widget.extend(/** @lends openerp.web.Notification# */{
template: 'Notification',
@@ -157,11 +158,9 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({
on_managed_error: function(error) {
$('<div>' + QWeb.render('DialogWarning', {error: error}) + '</div>').dialog({
title: "OpenERP " + _.str.capitalize(error.type),
- buttons: {
- Ok: function() {
- $(this).dialog("close");
- }
- }
+ buttons: [
+ {text: _t("Ok"), click: function() { $(this).dialog("close"); }}
+ ]
});
},
on_traceback: function(error) {
@@ -172,11 +171,9 @@ openerp.web.CrashManager = openerp.web.CallbackEnabled.extend({
height: '90%',
min_width: '800px',
min_height: '600px',
- buttons: {
- Ok: function() {
- $(this).dialog("close");
- }
- }
+ buttons: [
+ {text: _t("Ok"), click: function() { $(this).dialog("close"); }}
+ ]
}).start();
dialog.$element.html(QWeb.render('DialogTraceback', {error: error}));
}
@@ -368,11 +365,9 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
return $('<div>').dialog({
modal: true,
title: error.title,
- buttons: {
- Ok: function() {
- $(this).dialog("close");
- }
- }
+ buttons: [
+ {text: _t("Ok"), click: function() { $(this).dialog("close"); }}
+ ]
}).html(error.error);
},
do_create: function() {
@@ -634,9 +629,6 @@ openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{
callback: continuation || function() {}
});
},
- on_logout: function() {
- this.session.logout();
- }
});
openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# */{
@@ -663,7 +655,7 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# *
self.$content.remove();
if (!self.session.uid)
return;
- var func = new openerp.web.Model(self.session, "res.users").get_func("read");
+ var func = new openerp.web.Model("res.users").get_func("read");
return func(self.session.uid, ["name", "company_id"]).pipe(function(res) {
self.$content = $(QWeb.render("Header-content", {widget: self, user: res}));
self.$content.appendTo(self.$element);
@@ -680,7 +672,7 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# *
self.rpc("/web/webclient/version_info", {}).then(function(res) {
var $help = $(QWeb.render("About-Page", {version_info: res}));
$help.dialog({autoOpen: true,
- modal: true, width: 960, title: "About"});
+ modal: true, width: 960, title: _t("About")});
});
},
shortcut_load :function(){
@@ -760,25 +752,22 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# *
});
this.dialog = new openerp.web.Dialog(this,{
modal: true,
- title: 'Preferences',
+ title: _t("Preferences"),
width: 600,
height: 500,
- buttons: {
- "Change password": function(){
- self.change_password();
- },
- Cancel: function(){
- $(this).dialog('destroy');
- },
- Save: function(){
- var inner_viewmanager = action_manager.inner_viewmanager;
- inner_viewmanager.views[inner_viewmanager.active_view].controller.do_save()
- .then(function() {
- self.dialog.stop();
- window.location.reload();
- });
+ buttons: [
+ {text: _t("Change password"), click: function(){ self.change_password(); }},
+ {text: _t("Cancel"), click: function(){ $(this).dialog('destroy'); }},
+ {text: _t("Save"), click: function(){
+ var inner_viewmanager = action_manager.inner_viewmanager;
+ inner_viewmanager.views[inner_viewmanager.active_view].controller.do_save()
+ .then(function() {
+ self.dialog.stop();
+ window.location.reload();
+ });
+ }
}
- }
+ ]
});
this.dialog.start().open();
action_manager.appendTo(this.dialog);
@@ -789,7 +778,7 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# *
var self = this;
this.dialog = new openerp.web.Dialog(this,{
modal : true,
- title : 'Change Password',
+ title: _t("Change Password"),
width : 'auto',
height : 'auto'
});
@@ -814,11 +803,9 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# *
return $('<div>').dialog({
modal: true,
title: error.title,
- buttons: {
- Ok: function() {
- $(this).dialog("close");
- }
- }
+ buttons: [
+ {text: _("Ok"), click: function() { $(this).dialog("close"); }}
+ ]
}).html(error.error);
},
on_logout: function() {
@@ -966,13 +953,16 @@ openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{
$sub_menu.css(css);
$sub_menu.mouseenter(function() {
clearTimeout($sub_menu.data('timeoutId'));
+ $sub_menu.data('timeoutId', null);
+ return false;
}).mouseleave(function(evt) {
var timeoutId = setTimeout(function() {
- if (self.folded) {
- $sub_menu.hide();
+ if (self.folded && $sub_menu.data('timeoutId')) {
+ $sub_menu.hide().unbind('mouseenter').unbind('mouseleave');
}
}, self.float_timeout);
$sub_menu.data('timeoutId', timeoutId);
+ return false;
});
}
$sub_menu.show();
@@ -998,47 +988,56 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
* @param element_id
*/
init: function(element_id) {
+ var self = this;
this._super(null, element_id);
openerp.webclient = this;
- var params = {};
- if(jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) {
- this.$element.addClass("kitten-mode-activated");
- }
- this.$element.html(QWeb.render("Interface", params));
-
this.notification = new openerp.web.Notification(this);
this.loading = new openerp.web.Loading(this);
this.crashmanager = new openerp.web.CrashManager();
this.header = new openerp.web.Header(this);
this.login = new openerp.web.Login(this);
- this.header.on_logout.add(this.login.on_logout);
+ this.header.on_logout.add(this.on_logout);
this.header.on_action.add(this.on_menu_action);
- this.session.on_session_invalid.add(this.login.do_ask_login);
- this.session.on_session_valid.add_last(this.header.do_update);
- this.session.on_session_invalid.add_last(this.header.do_update);
- this.session.on_session_valid.add_last(this.on_logged);
- this.session.on_session_invalid.add_last(this.on_logged_out);
-
- this.menu = new openerp.web.Menu(this, "oe_menu", "oe_secondary_menu");
- this.menu.on_action.add(this.on_menu_action);
-
this._current_state = null;
-
},
start: function() {
this._super.apply(this, arguments);
- this.notification.prependTo(this.$element);
- this.loading.appendTo($('#oe_loading'));
- this.header.appendTo($("#oe_header"));
- this.session.start();
- this.login.appendTo($('#oe_login'));
- this.menu.start();
+ var self = this;
+ this.session.bind().then(function() {
+ var params = {};
+ if (jQuery.param != undefined && jQuery.deparam(jQuery.param.querystring()).kitten != undefined) {
+ this.$element.addClass("kitten-mode-activated");
+ this.$element.delegate('img.oe-record-edit-link-img', 'hover', function(e) {
+ self.$element.toggleClass('clark-gable');
+ });
+ }
+ self.$element.html(QWeb.render("Interface", params));
+ self.menu = new openerp.web.Menu(self, "oe_menu", "oe_secondary_menu");
+ self.menu.on_action.add(self.on_menu_action);
+
+ self.notification.prependTo(self.$element);
+ self.loading.appendTo($('#oe_loading'));
+ self.header.appendTo($("#oe_header"));
+ self.login.appendTo($('#oe_login'));
+ self.menu.start();
+ self.login.on_login_invalid();
+ });
+ this.session.ready.then(function() {
+ self.login.on_login_valid();
+ self.header.do_update();
+ self.menu.do_reload();
+ if(self.action_manager)
+ self.action_manager.stop();
+ self.action_manager = new openerp.web.ActionManager(this);
+ self.action_manager.appendTo($("#oe_app"));
+ self.bind_hashchange();
+ });
},
do_reload: function() {
- return $.when(this.session.session_restore(),this.menu.do_reload());
+ return $.when(this.session.session_init(),this.menu.do_reload());
},
do_notify: function() {
var n = this.notification;
@@ -1048,27 +1047,12 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
var n = this.notification;
n.warn.apply(n, arguments);
},
- on_logged: function() {
- this.menu.do_reload();
- if(this.action_manager)
- this.action_manager.stop();
- this.action_manager = new openerp.web.ActionManager(this);
- this.action_manager.do_push_state.add(this.do_push_state);
- this.action_manager.appendTo($("#oe_app"));
-
- if (openerp._modules_loaded) { // TODO: find better option than this
- this.bind_hashchange();
- } else {
- this.session.on_modules_loaded.add({ // XXX what about a $.Deferred ?
- callback: $.proxy(this, 'bind_hashchange'),
- unique: true,
- position: 'last'
- })
- }
- },
- on_logged_out: function() {
+ on_logout: function() {
+ this.session.session_logout();
+ this.login.on_login_invalid();
+ this.header.do_update();
$(window).unbind('hashchange', this.on_hashchange);
- this.do_push_state({},true);
+ this.do_push_state({});
if(this.action_manager)
this.action_manager.stop();
this.action_manager = null;
@@ -1090,11 +1074,7 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
}
this._current_state = state;
},
- do_push_state: function(state, overwrite) {
- if (!overwrite) {
- var hash = $.deparam.fragment(true);
- state = _.extend({}, hash, state);
- }
+ do_push_state: function(state) {
var url = '#' + $.param(state);
this._current_state = _.clone(state);
$.bbq.pushState(url);
@@ -1113,6 +1093,47 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
},
});
+openerp.currentScript = function() {
+ var currentScript = document.currentScript;
+ if (!currentScript) {
+ var sc = document.getElementsByTagName('script');
+ currentScript = sc[sc.length-1];
+ }
+ return currentScript;
+};
+
+openerp.web.EmbeddedClient = openerp.web.Widget.extend({
+ template: 'EmptyComponent',
+ init: function(action_id, options) {
+ this._super();
+ // TODO take the xmlid of a action instead of its id
+ this.action_id = action_id;
+ this.options = options || {};
+ this.am = new openerp.web.ActionManager(this);
+ },
+
+ start: function() {
+ var self = this;
+
+ this.am.appendTo(this.$element.addClass('openerp'));
+
+ return this.rpc("/web/action/load", { action_id: this.action_id }, function(result) {
+ var action = result.result;
+ action.flags = _.extend({
+ //views_switcher : false,
+ search_view : false,
+ action_buttons : false,
+ sidebar : false
+ //pager : false
+ }, self.options, action.flags || {});
+
+ self.am.do_action(action);
+ });
+ },
+
+});
+
+
};
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js
index d3734d29278..12422fb5434 100644
--- a/addons/web/static/src/js/core.js
+++ b/addons/web/static/src/js/core.js
@@ -254,14 +254,16 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
* Retrieves the object matching the provided key string.
*
* @param {String} key the key to fetch the object for
+ * @param {Boolean} [silent_error=false] returns undefined if the key or object is not found, rather than throwing an exception
* @returns {Class} the stored class, to initialize
*
* @throws {openerp.web.KeyNotFound} if the object was not in the mapping
* @throws {openerp.web.ObjectNotFound} if the object path was invalid
*/
- get_object: function (key) {
+ get_object: function (key, silent_error) {
var path_string = this.map[key];
if (path_string === undefined) {
+ if (silent_error) { return void 'nooo'; }
throw new openerp.web.KeyNotFound(key);
}
@@ -272,6 +274,7 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
object_match = object_match[path[i]];
if (object_match === undefined) {
+ if (silent_error) { return void 'noooooo'; }
throw new openerp.web.ObjectNotFound(path_string);
}
}
@@ -350,11 +353,19 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
* @param {String} [server] JSON-RPC endpoint hostname
* @param {String} [port] JSON-RPC endpoint port
*/
- init: function(server, port) {
+ init: function() {
this._super();
- this.server = (server == undefined) ? location.hostname : server;
- this.port = (port == undefined) ? location.port : port;
- this.rpc_mode = (server == location.hostname) ? "ajax" : "jsonp";
+ // TODO: session store in cookie should be optional
+ this.name = openerp._session_id;
+ },
+ bind: function(host, protocol) {
+ var self = this;
+ this.host = (host == undefined) ? location.host : host;
+ this.protocol = (protocol == undefined) ? location.protocol : protocol;
+ this.prefix = this.protocol + '//' + this.host;
+ openerp.web.qweb.default_dict['_s'] = this.prefix
+ this.rpc_mode = (this.host == location.host) ? "json" : "jsonp";
+ this.rpc_function = (this.host == location.host) ? this.rpc_json : this.rpc_jsonp;
this.debug = (window.location.search.indexOf('?debug') !== -1);
this.session_id = false;
this.uid = false;
@@ -366,14 +377,8 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
this.context = {};
this.shortcuts = [];
this.active_id = null;
- // TODO: session should have an optional name indicating that they'll
- // be saved to (and revived from) cookies
- this.name = 'session';
- this.do_load_qweb(['/web/webclient/qweb']);
- },
-
- start: function() {
- this.session_restore();
+ this.ready = $.Deferred();
+ return this.session_init();
},
/**
* Executes an RPC call, registering the provided callbacks.
@@ -390,82 +395,133 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
*/
rpc: function(url, params, success_callback, error_callback) {
var self = this;
+ // url can be an $.ajax option object
+ if (_.isString(url)) {
+ url = { url: url };
+ }
// Construct a JSON-RPC2 request, method is currently unused
params.session_id = this.session_id;
if (this.debug)
params.debug = 1;
-
- // Call using the rpc_mode
- var deferred = $.Deferred();
- this.rpc_ajax(url, {
- jsonrpc: "2.0",
- method: "call",
+ var payload = {
+ jsonrpc: '2.0',
+ method: 'call',
params: params,
- id: _.uniqueId('browser-client-')
- }).then(function () {deferred.resolve.apply(deferred, arguments);},
- function(error) {deferred.reject(error, $.Event());});
- return deferred.fail(function() {
+ id: _.uniqueId('r')
+ };
+ var deferred = $.Deferred();
+ this.on_rpc_request();
+ this.rpc_function(url, payload).then(
+ function (response, textStatus, jqXHR) {
+ self.on_rpc_response();
+ if (!response.error) {
+ deferred.resolve(response["result"], textStatus, jqXHR);
+ } else if (response.error.data.type === "session_invalid") {
+ self.uid = false;
+ // TODO deprecate or use a deferred on login.do_ask_login()
+ self.on_session_invalid(function() {
+ self.rpc(url, payload.params,
+ function() { deferred.resolve.apply(deferred, arguments); },
+ function() { deferred.reject.apply(deferred, arguments); });
+ });
+ } else {
+ deferred.reject(response.error, $.Event());
+ }
+ },
+ function(jqXHR, textStatus, errorThrown) {
+ self.on_rpc_response();
+ var error = {
+ code: -32098,
+ message: "XmlHttpRequestError " + errorThrown,
+ data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] }
+ };
+ deferred.reject(error, $.Event());
+ });
+ // Allow deferred user to disable on_rpc_error in fail
+ deferred.fail(function() {
deferred.fail(function(error, event) {
if (!event.isDefaultPrevented()) {
self.on_rpc_error(error, event);
}
});
}).then(success_callback, error_callback).promise();
+ return deferred;
},
/**
* Raw JSON-RPC call
*
* @returns {jQuery.Deferred} ajax-webd deferred object
*/
- rpc_ajax: function(url, payload) {
+ rpc_json: function(url, payload) {
var self = this;
- this.on_rpc_request();
- // url can be an $.ajax option object
- if (_.isString(url)) {
- url = {
- url: url
- }
- }
var ajax = _.extend({
type: "POST",
- url: url,
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(payload),
- processData: false
+ processData: false,
}, url);
- var deferred = $.Deferred();
- $.ajax(ajax).done(function(response, textStatus, jqXHR) {
- self.on_rpc_response();
- if (!response.error) {
- deferred.resolve(response["result"], textStatus, jqXHR);
- return;
- }
- if (response.error.data.type !== "session_invalid") {
- deferred.reject(response.error);
- return;
- }
- self.uid = false;
- self.on_session_invalid(function() {
- self.rpc(url, payload.params,
- function() {
- deferred.resolve.apply(deferred, arguments);
- },
- function(error, event) {
- event.preventDefault();
- deferred.reject.apply(deferred, arguments);
- });
- });
- }).fail(function(jqXHR, textStatus, errorThrown) {
- self.on_rpc_response();
- var error = {
- code: -32098,
- message: "XmlHttpRequestError " + errorThrown,
- data: {type: "xhr"+textStatus, debug: jqXHR.responseText, objects: [jqXHR, errorThrown] }
+ return $.ajax(ajax);
+ },
+ rpc_jsonp: function(url, payload) {
+ var self = this;
+ // extracted from payload to set on the url
+ var data = {
+ session_id: this.session_id,
+ id: payload.id,
+ };
+ url.url = this.get_url(url.url);
+ var ajax = _.extend({
+ type: "GET",
+ dataType: 'jsonp',
+ jsonp: 'jsonp',
+ cache: false,
+ data: data
+ }, url);
+ var payload_str = JSON.stringify(payload);
+ var payload_url = $.param({r:payload_str});
+ if(playload_url.length < 2000) {
+ // Direct jsonp request
+ ajax.data.r = payload_str;
+ return $.ajax(ajax);
+ } else {
+ // Indirect jsonp request
+ var ifid = _.uniqueId('oe_rpc_iframe');
+ var display = options.openerp.debug ? 'block' : 'none';
+ var $iframe = $(_.str.sprintf("<iframe src='javascript:false;' name='%s' id='%s' style='display:%s'></iframe>", ifid, ifid, display));
+ var $form = $('<form>')
+ .attr('method', 'POST')
+ .attr('target', ifid)
+ .attr('enctype', "multipart/form-data")
+ .attr('action', ajax.url + '?' + $.param(data))
+ .append($('<input type="hidden" name="r" />').attr('value', payload_str))
+ .hide()
+ .appendTo($('body'));
+ var cleanUp = function() {
+ if ($iframe) {
+ $iframe.unbind("load").attr("src", "javascript:false;").remove();
+ }
+ $form.remove();
};
- deferred.reject(error);
- });
- return deferred.promise();
+ var deferred = $.Deferred();
+ // the first bind is fired up when the iframe is added to the DOM
+ $iframe.bind('load', function() {
+ // the second bind is fired up when the result of the form submission is received
+ $iframe.unbind('load').bind('load', function() {
+ $.ajax(ajax).always(function() {
+ cleanUp();
+ }).then(
+ function() { deferred.resolve.apply(deferred, arguments); },
+ function() { deferred.reject.apply(deferred, arguments); }
+ );
+ });
+ // now that the iframe can receive data, we fill and submit the form
+ $form.submit();
+ });
+ // append the iframe to the DOM (will trigger the first load)
+ $form.after($iframe);
+ return deferred;
+ }
},
on_rpc_request: function() {
},
@@ -474,75 +530,51 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
on_rpc_error: function(error) {
},
/**
- * The session is validated either by login or by restoration of a previous session
- */
- on_session_valid: function() {
- if(!openerp._modules_loaded)
- this.load_modules();
- },
- on_session_invalid: function(contination) {
- },
- session_is_valid: function() {
- return this.uid;
- },
- session_authenticate: function(db, login, password, success_callback) {
- var self = this;
- var base_location = document.location.protocol + '//' + document.location.host;
- var params = { db: db, login: login, password: password, base_location: base_location };
- return this.rpc("/web/session/authenticate", params, function(result) {
- _.extend(self, {
- session_id: result.session_id,
- uid: result.uid,
- user_context: result.context,
- db: result.db,
- username: result.login
- });
- self.session_save();
- self.on_session_valid();
- return true;
- }).then(success_callback);
- },
- login: function() { this.session_authenticate.apply(this, arguments); },
- /**
- * Reloads uid and session_id from local storage, if they exist
+ * Init a session, reloads from cookie, if it exists
*/
- session_restore: function () {
+ session_init: function () {
var self = this;
+ // TODO: session store in cookie should be optional
this.session_id = this.get_cookie('session_id');
- return this.rpc("/web/session/get_session_info", {}).then(function(result) {
+ return this.rpc("/web/session/get_session_info", {}).pipe(function(result) {
// If immediately follows a login (triggered by trying to restore
// an invalid session or no session at all), refresh session data
- // (should not change, but just in case...) but should not call
- // on_session_valid again as it triggers reloading the menu
- var already_logged = self.uid;
+ // (should not change, but just in case...)
_.extend(self, {
- uid: result.uid,
- user_context: result.context,
db: result.db,
- username: result.login
+ username: result.login,
+ uid: result.uid,
+ user_context: result.context
});
- if (!already_logged) {
- if (self.uid) {
- self.on_session_valid();
- } else {
- self.on_session_invalid();
- }
+ var deferred = self.do_load_qweb(['/web/webclient/qweb']);
+ if(self.uid) {
+ return deferred.then(self.load_modules());
}
- }, function() {
- self.on_session_invalid();
+ return deferred;
});
},
/**
- * Saves the session id and uid locally
+ * The session is validated either by login or by restoration of a previous session
*/
- session_save: function () {
- this.set_cookie('session_id', this.session_id);
+ session_authenticate: function(db, login, password) {
+ var self = this;
+ var base_location = document.location.protocol + '//' + document.location.host;
+ var params = { db: db, login: login, password: password, base_location: base_location };
+ return this.rpc("/web/session/authenticate", params).pipe(function(result) {
+ _.extend(self, {
+ session_id: result.session_id,
+ db: result.db,
+ username: result.login,
+ uid: result.uid,
+ user_context: result.context
+ });
+ // TODO: session store in cookie should be optional
+ self.set_cookie('session_id', self.session_id);
+ return self.load_modules();
+ });
},
- logout: function() {
+ session_logout: function() {
this.set_cookie('session_id', '');
- this.reload_client();
- },
- reload_client: function() {
window.location.reload();
},
/**
@@ -586,23 +618,28 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
*/
load_modules: function() {
var self = this;
+ if(openerp._modules_loaded) {
+ return $.when();
+ }
this.rpc('/web/session/modules', {}, function(result) {
self.module_list = result;
var lang = self.user_context.lang;
var params = { mods: ["web"].concat(result), lang: lang};
- self.rpc('/web/webclient/translations',params).then(function(transs) {
+ self.rpc('/web/webclient/translations',params).pipe(function(transs) {
openerp.web._t.database.set_bundle(transs);
var modules = self.module_list.join(',');
var file_list = ["/web/static/lib/datejs/globalization/" +
self.user_context.lang.replace("_", "-") + ".js"
];
-
- self.rpc('/web/webclient/csslist', {"mods": modules}, self.do_load_css);
- self.rpc('/web/webclient/jslist', {"mods": modules}, function(files) {
- self.do_load_js(file_list.concat(files));
+ return $.when(
+ self.rpc('/web/webclient/csslist', {mods: modules}, self.do_load_css),
+ self.rpc('/web/webclient/qweblist', {mods: modules}).pipe(self.do_load_qweb),
+ self.rpc('/web/webclient/jslist', {mods: modules}).pipe(function(files) {
+ return self.do_load_js(file_list.concat(files));
+ })
+ ).then(function() {
+ self.ready.resolve();
});
- self.rpc('/web/webclient/qweblist', {"mods": modules}, self.do_load_qweb);
- openerp._modules_loaded = true;
});
});
},
@@ -610,7 +647,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
var self = this;
_.each(files, function (file) {
$('head').append($('<link>', {
- 'href': file,
+ 'href': self.get_url(file),
'rel': 'stylesheet',
'type': 'text/css'
}));
@@ -618,28 +655,39 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
},
do_load_js: function(files) {
var self = this;
+ var d = $.Deferred();
if(files.length != 0) {
var file = files.shift();
var tag = document.createElement('script');
tag.type = 'text/javascript';
- tag.src = file;
+ tag.src = self.get_url(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);
+ self.do_load_js(files).then(function () {
+ d.resolve();
+ });
};
var head = document.head || document.getElementsByTagName('head')[0];
head.appendChild(tag);
} else {
- this.on_modules_loaded();
+ self.on_modules_loaded();
+ d.resolve();
}
+ return d;
},
do_load_qweb: function(files) {
var self = this;
- _.each(files, function(file) {
- openerp.web.qweb.add_template(file);
- });
+ if (files.length != 0) {
+ var file = files.shift();
+ return self.rpc('/web/proxy/load', {path: file}).pipe(function(xml) {
+ openerp.web.qweb.add_template(_.str.trim(xml));
+ return self.do_load_qweb(files);
+ });
+ } else {
+ return $.when();
+ }
},
on_modules_loaded: function() {
for(var j=0; j<this.module_list.length; j++) {
@@ -654,6 +702,9 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
}
}
},
+ get_url: function (file) {
+ return this.prefix + file;
+ },
/**
* Cooperative file download implementation, for ajaxy APIs.
*
@@ -1069,6 +1120,7 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we
}
});
+/** Configure blockui */
if ($.blockUI) {
$.blockUI.defaults.baseZ = 1100;
$.blockUI.defaults.message = '<img src="/web/static/src/img/throbber2.gif">';
@@ -1100,6 +1152,7 @@ openerp.web.qweb.format_text_node = function(s) {
openerp.connection = new openerp.web.Connection();
openerp.web.qweb.default_dict['__debug__'] = openerp.connection.debug;
+/** Jquery extentions */
$.Mutex = (function() {
function Mutex() {
this.def = $.Deferred().resolve();
diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js
index 26147b4d4e0..46393aaf205 100644
--- a/addons/web/static/src/js/data.js
+++ b/addons/web/static/src/js/data.js
@@ -510,9 +510,10 @@ openerp.web.DataSetStatic = openerp.web.DataSet.extend({
},
set_ids: function (ids) {
this.ids = ids;
- if (this.index !== null) {
- this.index = this.index <= this.ids.length - 1 ?
- this.index : (this.ids.length > 0 ? this.length - 1 : 0);
+ if (ids.length === 0) {
+ this.index = null;
+ } else if (this.index >= ids.length - 1) {
+ this.index = ids.length - 1;
}
},
unlink: function(ids) {
@@ -811,7 +812,7 @@ openerp.web.ProxyDataSet = openerp.web.DataSetSearch.extend({
});
openerp.web.Model = openerp.web.CallbackEnabled.extend({
- init: function(_, model_name) {
+ init: function(model_name) {
this._super();
this.model_name = model_name;
},
diff --git a/addons/web/static/src/js/data_export.js b/addons/web/static/src/js/data_export.js
index ea142606b5b..8a2d2c8594b 100644
--- a/addons/web/static/src/js/data_export.js
+++ b/addons/web/static/src/js/data_export.js
@@ -1,8 +1,9 @@
openerp.web.data_export = function(openerp) {
-var QWeb = openerp.web.qweb;
+var QWeb = openerp.web.qweb,
+ _t = openerp.web._t;
openerp.web.DataExport = openerp.web.Dialog.extend({
template: 'ExportTreeView',
- dialog_title: 'Export Data',
+ dialog_title: {toString: function () { return _t("Export Data"); }},
init: function(parent, dataset) {
this._super(parent);
this.records = {};
@@ -18,14 +19,10 @@ openerp.web.DataExport = openerp.web.Dialog.extend({
width: '55%',
height: 'auto',
position: 'top',
- buttons : {
- "Close" : function() {
- self.close();
- },
- "Export To File" : function() {
- self.on_click_export_data();
- }
- },
+ buttons : [
+ {text: _t("Close"), click: function() { self.close(); }},
+ {text: _t("Export To File"), click: function() { self.on_click_export_data(); }}
+ ],
close: function(event, ui){ self.close();}
});
self.$element.removeClass('ui-dialog-content ui-widget-content');
diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js
index cd699c0481d..3d626db125d 100644
--- a/addons/web/static/src/js/data_import.js
+++ b/addons/web/static/src/js/data_import.js
@@ -31,7 +31,7 @@ function jsonp(form, attributes, callback) {
openerp.web.DataImport = openerp.web.Dialog.extend({
template: 'ImportDataView',
- dialog_title: "Import Data",
+ dialog_title: {toString: function () { return _t("Import Data"); }},
init: function(parent, dataset){
var self = this;
this._super(parent, {});
@@ -111,7 +111,11 @@ openerp.web.DataImport = openerp.web.Dialog.extend({
});
}
_(fields).each(function (field, field_name) {
- if (field_name === 'id') { return; }
+ // Ignore spec for id field
+ // Don't import function fields (function and related)
+ if (field_name === 'id' || 'function' in field) {
+ return;
+ }
var f = {
id: field_name,
name: field_name,
diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js
index 2df651158eb..264cc836e2d 100644
--- a/addons/web/static/src/js/formats.js
+++ b/addons/web/static/src/js/formats.js
@@ -254,7 +254,7 @@ openerp.web.format_cell = function (row_data, column, value_if_empty, process_mo
if (column.tag === 'button') {
return [
'<button type="button" title="', column.string || '', '">',
- '<img src="/web/static/src/img/icons/', column.icon, '.png"',
+ '<img src="', openerp.connection.prefix, '/web/static/src/img/icons/', column.icon, '.png"',
' alt="', column.string || '', '"/>',
'</button>'
].join('')
diff --git a/addons/web/static/src/js/view_editor.js b/addons/web/static/src/js/view_editor.js
index 352856c2b6c..f925a6416eb 100644
--- a/addons/web/static/src/js/view_editor.js
+++ b/addons/web/static/src/js/view_editor.js
@@ -35,28 +35,19 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({
pager: false,
radio: true,
select_view_id: self.parent.fields_view.view_id
- },
+ }
};
this.view_edit_dialog = new openerp.web.Dialog(this, {
modal: true,
- title: 'ViewEditor',
+ title: _t("ViewEditor"),
width: 750,
height: 500,
- buttons: {
- "Create": function(){
- self.on_create_view();
- },
- "Edit": function(){
- self.xml_element_id = 0;
- self.get_arch();
- },
- "Remove": function(){
- self.do_delete_view();
- },
- "Close": function(){
- self.view_edit_dialog.close();
- }
- },
+ buttons: [
+ {text: _t("Create"), click: function() { self.on_create_view(); }},
+ {text: _t("Edit"), click: function() { self.xml_element_id = 0; self.get_arch(); }},
+ {text: _t("Remove"), click: function() { self.do_delete_view(); }},
+ {text: _t("Close"), click: function() { self.view_edit_dialog.close(); }}
+ ]
}).start().open();
this.main_view_id = this.parent.fields_view.view_id;
this.action_manager = new openerp.web.ActionManager(this);
@@ -77,36 +68,34 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({
var self = this;
this.create_view_dialog = new openerp.web.Dialog(this, {
modal: true,
- title: _.str.sprintf("Create a view (%s)", self.model),
+ title: _.str.sprintf(_t("Create a view (%s)"), self.model),
width: 500,
height: 400,
- buttons: {
- "Save": function(){
- var view_values = {};
- var warn = false;
- _.each(self.create_view_widget, function(widget) {
- if (widget.is_invalid) {
- warn = true;
- return false;
- };
- if (widget.dirty && !widget.is_invalid) {
- view_values[widget.name] = widget.get_value();
- }
- });
- if (warn) {
- self.on_valid_create_view(self.create_view_widget);
- } else {
- $.when(self.do_save_view(view_values)).then(function() {
- self.create_view_dialog.close();
- var controller = self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller;
- controller.reload_content();
- });
+ buttons: [
+ {text: _t("Save"), click: function () {
+ var view_values = {};
+ var warn = false;
+ _.each(self.create_view_widget, function(widget) {
+ if (widget.is_invalid) {
+ warn = true;
+ return false;
}
- },
- "Cancel": function(){
- self.create_view_dialog.close();
+ if (widget.dirty && !widget.is_invalid) {
+ view_values[widget.name] = widget.get_value();
+ }
+ });
+ if (warn) {
+ self.on_valid_create_view(self.create_view_widget);
+ } else {
+ $.when(self.do_save_view(view_values)).then(function() {
+ self.create_view_dialog.close();
+ var controller = self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller;
+ controller.reload_content();
+ });
}
- }
+ }},
+ {text: _t("Cancel"), click: function () { self.create_view_dialog.close(); }}
+ ]
});
this.create_view_dialog.start().open();
var view_widget = [{'name': 'view_name', 'string':'View Name', 'type': 'char', 'required': true, 'value' : this.model + '.custom_' + Math.round(Math.random() * 1000)},
@@ -375,11 +364,11 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({
this.one_object = one_object;
this.edit_xml_dialog = new openerp.web.Dialog(this, {
modal: true,
- title: _.str.sprintf("View Editor %d - %s", self.main_view_id, self.model),
+ title: _.str.sprintf(_t("View Editor %d - %s"), self.main_view_id, self.model),
width: 750,
height: 500,
- buttons: {
- "Preview": function() {
+ buttons: [
+ {text: _t("Preview"), click: function() {
var action = {
context: self.session.user_context,
res_model: self.model,
@@ -389,16 +378,16 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({
flags: {
sidebar: false,
views_switcher: false,
- action_buttons: false,
- },
+ action_buttons: false
+ }
};
var action_manager = new openerp.web.ActionManager(self);
action_manager.do_action(action);
- },
- "Close": function(){
+ }},
+ {text: _t("Close"), click: function(){
self.edit_xml_dialog.close();
- }
- }
+ }}
+ ]
}).start().open();
var no_property_att = [];
_.each(_PROPERTIES, function(val, key) {
@@ -764,17 +753,17 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({
var self = this;
this.edit_node_dialog = new openerp.web.Dialog(this,{
modal: true,
- title: 'Properties',
+ title: _t("Properties"),
width: 500,
height: 400,
- buttons: {
- "Update": function(){
+ buttons: [
+ {text: _t("Update"), click: function () {
var warn = false, update_values = [];
_.each(self.edit_widget, function(widget) {
if (widget.is_invalid) {
warn = true;
return false;
- };
+ }
if (widget.dirty && !widget.is_invalid) {
update_values.push([widget.name, widget.get_value()]);
}
@@ -785,11 +774,9 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({
self.do_save_update_arch("update_node", update_values);
self.edit_node_dialog.close();
}
- },
- "Cancel": function(){
- self.edit_node_dialog.close();
- }
- }
+ }},
+ {text: _t("Cancel"), click: function () { self.edit_node_dialog.close(); }}
+ ]
});
this.edit_node_dialog.start().open();
var _PROPERTIES_ATTRIBUTES = {
@@ -893,32 +880,32 @@ openerp.web.ViewEditor = openerp.web.Widget.extend({
this.add_widget = [];
this.add_node_dialog = new openerp.web.Dialog(this,{
modal: true,
- title: 'Properties',
+ title: _t("Properties"),
width: 450,
height: 190,
- buttons: {
- "Update": function(){
- var check_add_node = true, values = {};
- _.each(self.add_widget, function(widget) {
- values[widget.name] = widget.get_value() || false;
- });
- (values.position == "Inside")?
- check_add_node =(_.include(_CHILDREN[properties[0]],values.node_type))?true:false:
- check_add_node =(_.include(_CHILDREN[properties[1]],values.node_type))?true:false;
- if(values.node_type == "field" && check_add_node )
- {check_add_node = (values.field_value != " ")?true:false;
- }
- if(check_add_node){
- var tag = (values.node_type == "field")?
- _.str.sprintf("<%s name='%s'> </%s>",values.node_type,values.field_value,values.node_type):
- _.str.sprintf("<%s> </%s>",values.node_type,values.node_type);
- self.do_save_update_arch("add_node", [tag, values.position]);
- }else{alert("Can't Update View");}
- },
- "Cancel": function(){
- self.add_node_dialog.close();
+ buttons: [
+ {text: _t("Update"), click: function() {
+ var check_add_node = true, values = {};
+ _.each(self.add_widget, function(widget) {
+ values[widget.name] = widget.get_value() || false;
+ });
+ (values.position == "Inside")?
+ check_add_node =(_.include(_CHILDREN[properties[0]],values.node_type))?true:false:
+ check_add_node =(_.include(_CHILDREN[properties[1]],values.node_type))?true:false;
+ if(values.node_type == "field" && check_add_node )
+ {check_add_node = (values.field_value != " ")?true:false;
}
- }
+ if(check_add_node){
+ var tag = (values.node_type == "field")?
+ _.str.sprintf("<%s name='%s'> </%s>",values.node_type,values.field_value,values.node_type):
+ _.str.sprintf("<%s> </%s>",values.node_type,values.node_type);
+ self.do_save_update_arch("add_node", [tag, values.position]);
+ } else {
+ alert("Can't Update View");
+ }
+ }},
+ {text: _t("Cancel"), click: function() { self.add_node_dialog.close(); }}
+ ]
}).start().open();
this.add_node_dialog.$element.append('<table id="rec_table" style="width:420px" class="oe_forms"><tbody><tr></tbody></table>');
var table_selector = self.add_node_dialog.$element.find('table[id=rec_table] tbody');
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 5908dc67dc6..0d962353b78 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -13,6 +13,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
readonly : false,
form_template: "FormView",
identifier_prefix: 'formview-',
+ display_name: {toString: function () { return _t('Form'); }},
/**
* @constructs openerp.web.FormView
* @extends openerp.web.View
@@ -117,6 +118,18 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
}
this.has_been_loaded.resolve();
},
+
+ do_load_state: function(state) {
+ if (state.id && this.datarecord.id != state.id) {
+ var idx = this.dataset.get_id_index(state.id);
+ if (idx === null) {
+ this.dataset.ids.push(state.id)
+ this.dataset.index = this.dataset.ids.length - 1;
+ }
+ this.do_show();
+ }
+ },
+
do_show: function () {
var promise;
if (this.dataset.index === null) {
@@ -132,7 +145,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
return promise;
},
do_hide: function () {
- this.$element.hide();
+ this._super();
if (this.sidebar) {
this.sidebar.$element.hide();
}
@@ -140,7 +153,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
on_record_loaded: function(record) {
var self = this, set_values = [];
if (!record) {
- throw("Form: No record received");
+ throw new Error("Form: No record received");
}
this.datarecord = record;
@@ -175,6 +188,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
if (self.default_focus_field && !self.embedded_view) {
self.default_focus_field.focus();
}
+ if (record.id) {
+ self.do_push_state({id:record.id});
+ }
});
},
on_form_changed: function() {
@@ -334,11 +350,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
if (!_.isEmpty(result.warning)) {
$(QWeb.render("DialogWarning", result.warning)).dialog({
modal: true,
- buttons: {
- Ok: function() {
- $(this).dialog("close");
- }
- }
+ buttons: [
+ {text: _t("Ok"), click: function() { $(this).dialog("close"); }}
+ ]
});
}
if (result.domain) {
@@ -626,7 +640,7 @@ openerp.web.form.SidebarAttachments = openerp.web.Widget.extend({
on_attachment_delete: function(e) {
var self = this, $e = $(e.currentTarget);
var name = _.str.trim($e.parent().find('a.oe-sidebar-attachments-link').text());
- if (confirm("Do you really want to delete the attachment " + name + " ?")) {
+ if (confirm(_.sprintf(_t("Do you really want to delete the attachment %s?"), name))) {
this.rpc('/web/dataset/unlink', {
model: 'ir.attachment',
ids: [parseInt($e.attr('data-id'))]
@@ -1048,20 +1062,22 @@ openerp.web.form.WidgetButton = openerp.web.form.Widget.extend({
if (self.node.attrs.confirm) {
var def = $.Deferred();
var dialog = $('<div>' + self.node.attrs.confirm + '</div>').dialog({
- title: 'Confirm',
+ title: _t('Confirm'),
modal: true,
- buttons: {
- Ok: function() {
- self.on_confirmed().then(function() {
- def.resolve();
- });
- $(this).dialog("close");
+ buttons: [
+ {text: _t("Ok"), click: function() {
+ self.on_confirmed().then(function() {
+ def.resolve();
+ });
+ $(this).dialog("close");
+ }
},
- Cancel: function() {
- def.resolve();
- $(this).dialog("close");
+ {text: _t("Cancel"), click: function() {
+ def.resolve();
+ $(this).dialog("close");
+ }
}
- }
+ ]
});
return def.promise();
} else {
@@ -2055,7 +2071,9 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({
});
this.views = views;
- this.viewmanager = new openerp.web.ViewManager(this, this.dataset, views);
+ this.viewmanager = new openerp.web.ViewManager(this, this.dataset, views, {
+ action_buttons : false
+ });
this.viewmanager.template = 'One2Many.viewmanager';
this.viewmanager.registry = openerp.web.views.clone({
list: 'openerp.web.form.One2ManyListView',
@@ -2083,7 +2101,6 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({
controller.on_pager_action.add_first(function() {
self.save_any_view();
});
- controller.$element.find(".oe_form_button_save").hide();
} else if (view_type == "graph") {
self.reload_current_view()
}
@@ -2370,7 +2387,7 @@ openerp.web.form.FieldMany2Many = openerp.web.form.Field.extend({
load_view: function() {
var self = this;
this.list_view = new openerp.web.form.Many2ManyListView(this, this.dataset, false, {
- 'addable': self.is_readonly() ? null : 'Add',
+ 'addable': self.is_readonly() ? null : _t("Add"),
'deletable': self.is_readonly() ? false : true,
'selectable': self.multi_selection
});
@@ -2905,13 +2922,18 @@ openerp.web.form.FieldBinaryFile = openerp.web.form.FieldBinary.extend({
},
set_value: function(value) {
this._super.apply(this, arguments);
- var show_value = (value != null && value !== false) ? value : '';
+ var show_value;
+ if (this.node.attrs.filename) {
+ show_value = this.view.datarecord[this.node.attrs.filename] || '';
+ } else {
+ show_value = (value != null && value !== false) ? value : '';
+ }
this.$element.find('input').eq(0).val(show_value);
},
on_file_uploaded_and_valid: function(size, name, content_type, file_base64) {
this.value = file_base64;
this.binary_value = true;
- var show_value = this.human_filesize(size);
+ var show_value = name + " (" + this.human_filesize(size) + ")";
this.$element.find('input').eq(0).val(show_value);
this.set_filename(name);
},
diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js
index bf423434ecc..8ed475c75f6 100644
--- a/addons/web/static/src/js/view_list.js
+++ b/addons/web/static/src/js/view_list.js
@@ -4,6 +4,7 @@ var QWeb = openerp.web.qweb;
openerp.web.views.add('list', 'openerp.web.ListView');
openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# */ {
_template: 'ListView',
+ display_name: {toString: function () { return _t('List'); }},
defaults: {
// records can be selected one by one
'selectable': true,
@@ -12,12 +13,14 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
// whether the column headers should be displayed
'header': true,
// display addition button, with that label
- 'addable': _t("Create"),
+ 'addable': {toString: function () { return _t("Create"); }},
// whether the list view can be sorted, note that once a view has been
// sorted it can not be reordered anymore
'sortable': true,
// whether the view rows can be reordered (via vertical drag & drop)
- 'reorderable': true
+ 'reorderable': true,
+ // display an edit icon linking to form view
+ 'isClarkGable': true
},
/**
* Core class for list-type displays.
@@ -120,8 +123,8 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
'action': function (e, action_name, id, callback) {
self.do_button_action(action_name, id, callback);
},
- 'row_link': function (e, id, dataset) {
- self.do_activate_record(dataset.index, id, dataset);
+ 'row_link': function (e, id, dataset, view) {
+ self.do_activate_record(dataset.index, id, dataset, view);
}
});
},
@@ -402,13 +405,13 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
}, this));
},
do_show: function () {
- this.$element.show();
+ this._super();
if (this.sidebar) {
this.sidebar.$element.show();
}
},
do_hide: function () {
- this.$element.hide();
+ this._super();
if (this.sidebar) {
this.sidebar.$element.hide();
}
@@ -457,8 +460,32 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
self.compute_aggregates();
reloaded.resolve();
}));
+ this.do_push_state({
+ page: this.page,
+ limit: this._limit,
+ });
return reloaded.promise();
},
+
+ do_load_state: function(state) {
+ var reload = false;
+ if (state.page && this.page !== state.page) {
+ this.page = state.page;
+ reload = true;
+ }
+ if (state.limit) {
+ if (_.isString(state.limit)) {
+ state.limit = null;
+ }
+ if (state.limit !== this._limit) {
+ this._limit = state.limit;
+ reload = true;
+ }
+ }
+ if (reload) {
+ this.reload_content();
+ }
+ },
/**
* Handler for the result of eval_domain_and_context, actually perform the
* searching
@@ -556,9 +583,9 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
* @param {Object} id identifier of the activated record
* @param {openerp.web.DataSet} dataset dataset in which the record is available (may not be the listview's dataset in case of nested groups)
*/
- do_activate_record: function (index, id, dataset) {
+ do_activate_record: function (index, id, dataset, view) {
this.dataset.ids = dataset.ids;
- this.select_record(index);
+ this.select_record(index, view);
},
/**
* Handles signal for the addition of a new record (can be a creation,
@@ -818,15 +845,19 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis
if (!self.dataset.select_id(row_id)) {
throw "Could not find id in dataset"
}
- self.row_clicked(e);
+ var view;
+ if ($(e.target).is('.oe-record-edit-link-img')) {
+ view = 'form';
+ }
+ self.row_clicked(e, view);
}
});
},
- row_clicked: function () {
+ row_clicked: function (e, view) {
$(this).trigger(
'row_link',
[this.dataset.ids[this.dataset.index],
- this.dataset]);
+ this.dataset, view]);
},
render_cell: function (record, column) {
var value;
@@ -887,6 +918,9 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis
if (this.options.selectable) {
cells.push('<th class="oe-record-selector"></td>');
}
+ if (this.options.isClarkGable) {
+ cells.push('<th class="oe-record-edit-link"></td>');
+ }
_(this.columns).each(function(column) {
if (column.invisible === '1') {
return;
diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js
index b2edf55b314..453536f7ec6 100644
--- a/addons/web/static/src/js/view_list_editable.js
+++ b/addons/web/static/src/js/view_list_editable.js
@@ -116,7 +116,7 @@ openerp.web.list_editable = function (openerp) {
openerp.web.ListView.List.include(/** @lends openerp.web.ListView.List# */{
row_clicked: function (event) {
if (!this.options.editable) {
- return this._super(event);
+ return this._super.apply(this, arguments);
}
this.edit_record($(event.currentTarget).data('id'));
},
@@ -248,7 +248,10 @@ openerp.web.list_editable = function (openerp) {
.end()
.find('td:last').removeClass('oe-field-cell').end();
if (self.options.selectable) {
- $new_row.prepend('<td>');
+ $new_row.prepend('<th>');
+ }
+ if (self.options.isClarkGable) {
+ $new_row.prepend('<th>');
}
// pad in case of groupby
_(self.columns).each(function (column) {
diff --git a/addons/web/static/src/js/view_page.js b/addons/web/static/src/js/view_page.js
index 40ca1176c79..1b23198da67 100644
--- a/addons/web/static/src/js/view_page.js
+++ b/addons/web/static/src/js/view_page.js
@@ -5,6 +5,7 @@ openerp.web.page = function (openerp) {
openerp.web.views.add('page', 'openerp.web.PageView');
openerp.web.PageView = openerp.web.FormView.extend({
form_template: "PageView",
+ display_name: {toString: function () { return _t('Page'); }},
init: function () {
this._super.apply(this, arguments);
this.registry = openerp.web.page.readonly;
@@ -200,6 +201,27 @@ openerp.web.page = function (openerp) {
openerp.web.page.FieldOne2ManyReadonly = openerp.web.form.FieldOne2Many.extend({
force_readonly: true
});
+ openerp.web.page.FieldBinaryFileReadonly = openerp.web.form.FieldBinary.extend({
+ template: 'FieldURI.readonly',
+ start: function() {
+ this._super.apply(this, arguments);
+ var self = this;
+ this.$element.find('a').click(function() {
+ if (self.value) {
+ self.on_save_as();
+ }
+ return false;
+ });
+ },
+ set_value: function(value) {
+ this._super.apply(this, arguments);
+ this.$element.find('a').show(!!value);
+ if (value) {
+ var show_value = _t("Download") + " " + (this.view.datarecord[this.node.attrs.filename] || '');
+ this.$element.find('a').text(show_value);
+ }
+ }
+ });
openerp.web.page.readonly = openerp.web.form.widgets.clone({
'frame': 'openerp.web.page.WidgetFrameReadonly',
'char': 'openerp.web.page.FieldCharReadonly',
@@ -218,6 +240,7 @@ openerp.web.page = function (openerp) {
'boolean': 'openerp.web.page.FieldBooleanReadonly',
'float': 'openerp.web.page.FieldCharReadonly',
'integer': 'openerp.web.page.FieldCharReadonly',
- 'float_time': 'openerp.web.page.FieldCharReadonly'
+ 'float_time': 'openerp.web.page.FieldCharReadonly',
+ 'binary': 'openerp.web.page.FieldBinaryFileReadonly',
});
};
diff --git a/addons/web/static/src/js/view_tree.js b/addons/web/static/src/js/view_tree.js
index 34d47b92813..48f7290c8d9 100644
--- a/addons/web/static/src/js/view_tree.js
+++ b/addons/web/static/src/js/view_tree.js
@@ -3,10 +3,12 @@
*---------------------------------------------------------*/
openerp.web.view_tree = function(openerp) {
-var QWeb = openerp.web.qweb;
+var QWeb = openerp.web.qweb,
+ _t = openerp.web._t;
openerp.web.views.add('tree', 'openerp.web.TreeView');
openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView# */{
+ display_name: {toString: function () { return _t('Tree'); }},
/**
* Indicates that this view is not searchable, and thus that no search
* view should be displayed (if there is one active).
@@ -111,6 +113,9 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView#
}
});
+ // TODO store open nodes in url ?...
+ this.do_push_state({});
+
if (!this.fields_view.arch.attrs.colors) {
return;
}
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index 0ad49f69f7b..5800939ec36 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -20,6 +20,7 @@ session.web.ActionManager = session.web.Widget.extend({
identifier_prefix: "actionmanager",
init: function(parent) {
this._super(parent);
+ this.inner_action = null;
this.inner_viewmanager = null;
this.dialog = null;
this.dialog_viewmanager = null;
@@ -46,37 +47,47 @@ session.web.ActionManager = session.web.Widget.extend({
this.client_widget = null;
}
},
-
- do_push_state: function(state, overwrite) {
+ do_push_state: function(state) {
+ if (this.widget_parent && this.widget_parent.do_push_state) {
+ if (this.inner_action && this.inner_action.id) {
+ state['action_id'] = this.inner_action.id;
+ }
+ this.widget_parent.do_push_state(state);
+ }
},
-
do_load_state: function(state) {
+ var self = this,
+ action_loaded;
if (state.action_id) {
- this.null_action();
- this.do_action(state.action_id);
+ var run_action = (!this.inner_viewmanager) || this.inner_viewmanager.action.id !== state.action_id;
+ if (run_action) {
+ this.null_action();
+ action_loaded = this.do_action(state.action_id);
+ }
}
else if (state.model && state.id) {
// TODO implement it
//this.null_action();
- // action = {}
+ //action = {res_model: state.model, res_id: state.id};
+ //action_loaded = this.do_action(action);
}
else if (state.client_action) {
this.null_action();
this.ir_actions_client(state.client_action);
}
- if (this.inner_viewmanager) {
- this.inner_viewmanager.do_load_state(state);
- }
+ $.when(action_loaded || null).then(function() {
+ if (self.inner_viewmanager) {
+ self.inner_viewmanager.do_load_state(state);
+ }
+ });
},
-
do_action: function(action, on_close) {
if (_.isNumber(action)) {
var self = this;
- self.rpc("/web/action/load", { action_id: action }, function(result) {
+ return self.rpc("/web/action/load", { action_id: action }, function(result) {
self.do_action(result.result, on_close);
});
- return;
}
if (!action.type) {
console.error("No type for action", action);
@@ -128,10 +139,6 @@ session.web.ActionManager = session.web.Widget.extend({
this.content_stop();
this.inner_action = action;
this.inner_viewmanager = new session.web.ViewManagerAction(this, action);
- this.inner_viewmanager.do_push_state.add(function(state,overwrite) {
- state['action_id'] = action.id;
- self.do_push_state(state,true);
- });
this.inner_viewmanager.appendTo(this.$element);
}
},
@@ -152,12 +159,9 @@ session.web.ActionManager = session.web.Widget.extend({
},
ir_actions_client: function (action) {
this.content_stop();
+ this.dialog_stop();
var ClientWidget = session.web.client_actions.get_object(action.tag);
(this.client_widget = new ClientWidget(this, action.params)).appendTo(this);
-
- var client_action = {tag: action.tag};
- if (action.params) _.extend(client_action, {params: action.params});
- this.do_push_state({client_action: client_action}, true);
},
ir_actions_report_xml: function(action, on_closed) {
var self = this;
@@ -200,15 +204,26 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View
* @param dataset
* @param views
*/
- init: function(parent, dataset, views) {
+ init: function(parent, dataset, views, flags) {
this._super(parent);
this.model = dataset ? dataset.model : undefined;
this.dataset = dataset;
this.searchview = null;
this.active_view = null;
- this.views_src = _.map(views, function(x) {return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
+ this.views_src = _.map(views, function(x) {
+ if (x instanceof Array) {
+ var View = session.web.views.get_object(x[1], true);
+ return {
+ view_id: x[0],
+ view_type: x[1],
+ label: View ? View.prototype.display_name : (void 'nope')
+ };
+ } else {
+ return x;
+ }
+ });
this.views = {};
- this.flags = this.flags || {};
+ this.flags = flags || {};
this.registry = session.web.views;
this.views_history = [];
},
@@ -314,8 +329,6 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View
});
return view_promise;
},
-
-
/**
* Returns to the view preceding the caller view in this manager's
* navigation history (the navigation history is appended to via
@@ -391,7 +404,8 @@ session.web.ViewManager = session.web.Widget.extend(/** @lends session.web.View
/**
* Called by children view after executing an action
*/
- on_action_executed: function () {},
+ on_action_executed: function () {
+ },
display_title: function () {
var view = this.views[this.active_view];
if (view) {
@@ -415,19 +429,10 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner
// dataset initialization will take the session from ``this``, so if we
// do not have it yet (and we don't, because we've not called our own
// ``_super()``) rpc requests will blow up.
- this._super(parent, null, action.views);
- this.session = parent.session;
- this.action = action;
- var dataset = new session.web.DataSetSearch(this, action.res_model, action.context, action.domain);
- if (action.res_id) {
- dataset.ids.push(action.res_id);
- dataset.index = 0;
- }
- this.dataset = dataset;
- this.flags = this.action.flags || {};
+ var flags = action.flags || {};
if (action.res_model == 'board.board' && action.view_mode === 'form') {
// Special case for Dashboards
- _.extend(this.flags, {
+ _.extend(flags, {
views_switcher : false,
display_title : false,
search_view : false,
@@ -436,6 +441,15 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner
action_buttons : false
});
}
+ this._super(parent, null, action.views, flags);
+ this.session = parent.session;
+ this.action = action;
+ var dataset = new session.web.DataSetSearch(this, action.res_model, action.context, action.domain);
+ if (action.res_id) {
+ dataset.ids.push(action.res_id);
+ dataset.index = 0;
+ }
+ this.dataset = dataset;
// setup storage for session-wise menu hiding
if (this.session.hidden_menutips) {
@@ -466,12 +480,6 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner
var main_view_loaded = this._super();
- _.each(_.keys(this.views), function(view_type) {
- $.when(self.views[view_type].deferred).done(function(view_type) {
- self.views[view_type].controller.do_push_state.add(self.do_push_state);
- });
- });
-
var manager_ready = $.when(searchview_loaded, main_view_loaded);
this.$element.find('.oe_debug_view').change(this.on_debug_changed);
@@ -584,21 +592,25 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner
} else {
$search_prefix.remove();
}
-
- self.do_push_state({view_type: self.active_view});
});
},
-
- do_push_state: function(state, overwrite) {
+ do_push_state: function(state) {
+ if (this.widget_parent && this.widget_parent.do_push_state) {
+ state["view_type"] = this.active_view;
+ this.widget_parent.do_push_state(state);
+ }
},
-
do_load_state: function(state) {
- var self = this;
- $.when(this.on_mode_switch(state.view_type, true)).done(function() {
+ var self = this,
+ defs = [];
+ if (state.view_type && state.view_type !== this.active_view) {
+ defs.push(this.on_mode_switch(state.view_type, true));
+ }
+
+ $.when(defs).then(function() {
self.views[self.active_view].controller.do_load_state(state);
});
},
-
shortcut_check : function(view) {
var self = this;
var grandparent = this.widget_parent && this.widget_parent.widget_parent;
@@ -851,7 +863,7 @@ session.web.Sidebar = session.web.Widget.extend({
});
session.web.TranslateDialog = session.web.Dialog.extend({
- dialog_title: _t("Translations"),
+ dialog_title: {toString: function () { return _t("Translations"); }},
init: function(view) {
// TODO fme: should add the language to fields_view_get because between the fields view get
// and the moment the user opens the translation dialog, the user language could have been changed
@@ -966,6 +978,8 @@ session.web.TranslateDialog = session.web.Dialog.extend({
session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{
template: "EmptyComponent",
+ // name displayed in view switchers
+ display_name: '',
set_default_options: function(options) {
this.options = options || {};
_.defaults(this.options, {
@@ -1064,19 +1078,33 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{
this.embedded_view = embedded_view;
this.options.sidebar = false;
},
+ do_show: function () {
+ this.$element.show();
+ },
+ do_hide: function () {
+ this.$element.hide();
+ },
+ do_push_state: function(state) {
+ if (this.widget_parent && this.widget_parent.do_push_state) {
+ this.widget_parent.do_push_state(state);
+ }
+ },
+ do_load_state: function(state) {
+ },
/**
* Switches to a specific view type
*
* @param {String} view view type to switch to
*/
- do_switch_view: function(view) { },
+ do_switch_view: function(view) {
+ },
/**
* Cancels the switch to the current view, switches to the previous one
*/
- do_prev_view: function () { },
+ do_prev_view: function () {
+ },
do_search: function(view) {
},
-
set_common_sidebar_sections: function(sidebar) {
sidebar.add_default_sections();
},
@@ -1144,12 +1172,6 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{
},
sidebar_context: function () {
return $.Deferred().resolve({}).promise();
- },
-
- do_push_state: function(state, overwrite) {
- },
-
- do_load_state: function(state) {
}
});
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 785eb285922..14f60c2dc9a 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -266,7 +266,7 @@
<form class="oe_forms">
<fieldset>
<legend style="">
- <img src="/web/static/src/img/stock_person.png" alt="" />
+ <img t-att-src='_s + "/web/static/src/img/stock_person.png"' alt="" />
</legend>
<div class="oe_box2">
<table align="center" cellspacing="2px" cellpadding="0">
@@ -306,7 +306,7 @@
<tbody>
<tr>
<td>
- <img src="/web/static/src/img/product.png"/>
+ <img t-att-src='_s + "/web/static/src/img/product.png"'/>
</td>
<td>
<strong>Full featured</strong><br />
@@ -315,7 +315,7 @@
</tr>
<tr>
<td>
- <img src="/web/static/src/img/accessories-archiver.png"/>
+ <img t-att-src='_s + "/web/static/src/img/accessories-archiver.png"'/>
</td>
<td>
<strong>Open Source</strong><br />
@@ -324,7 +324,7 @@
</tr>
<tr>
<td>
- <img src="/web/static/src/img/partner.png" />
+ <img t-att-src='_s + "/web/static/src/img/partner.png"' />
</td>
<td>
<strong>User Friendly</strong><br />
@@ -352,13 +352,13 @@
<div class="header_corner">
<ul class="block">
<li>
- <a t-att-href="'/' + widget.qs" title="Home" class="home"><img src="/web/static/src/img/header-home.png" width="16" height="16" border="0"/></a>
+ <a t-att-href="'/' + widget.qs" title="Home" class="home"><img t-att-src='_s + "/web/static/src/img/header-home.png"' width="16" height="16" border="0"/></a>
</li>
<li class="preferences">
- <a href="javascript:void(0)" title="Preferences" class="preferences"><img src="/web/static/src/img/header-preferences.png" width="16" height="16" border="0"/></a>
+ <a href="javascript:void(0)" title="Preferences" class="preferences"><img t-att-src='_s + "/web/static/src/img/header-preferences.png"' width="16" height="16" border="0"/></a>
</li>
<li>
- <a href="javascript:void(0)" title="About" class="about"><img src="/web/static/src/img/header-about.png" width="16" height="16" border="0"/></a>
+ <a href="javascript:void(0)" title="About" class="about"><img t-att-src='_s + "/web/static/src/img/header-about.png"' width="16" height="16" border="0"/></a>
</li>
</ul>
<div class="block">
@@ -423,7 +423,10 @@
</h2>
<div class="oe_vm_switch">
<t t-if="views.length != 1" t-foreach="views" t-as="view">
- <button type="button" t-att-data-view-type="view.view_type" t-att-title="view.view_type"></button>
+
+ <button type="button" t-att-data-view-type="view.view_type" t-att-title="view.view_type">
+
+ </button>
</t>
</div>
</div>
@@ -565,7 +568,7 @@
</tr>
<table t-name="ListView" class="oe-listview-content">
- <t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/>
+ <t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0) + (options.isClarkGable ? 1 : 0)"/>
<thead class="ui-widget-header">
<tr t-if="options.action_buttons !== false or options.pager !== false">
<th t-att-colspan="columns_count">
@@ -594,6 +597,7 @@
</t>
<th t-if="options.selectable" width="1" >
<input type="checkbox" class="all-record-selector"/> </th>
+ <th t-if="options.isClarkGable" width="1"> </th>
<t t-foreach="columns" t-as="column">
<th t-if="!column.meta and column.invisible !== '1'" t-att-data-id="column.id"
t-att-class="((options.sortable and column.tag !== 'button') ? 'oe-sortable' : null)">
@@ -607,6 +611,7 @@
<tfoot class="ui-widget-header">
<tr>
<td t-if="options.selectable"/>
+ <td t-if="options.isClarkGable"/>
<td t-foreach="aggregate_columns" t-as="column" class="oe-list-footer oe-number"
t-att-data-field="column.id" t-att-title="column.label">
</td>
@@ -664,6 +669,9 @@
<th t-if="options.selectable" class="oe-record-selector" width="1">
<input t-att-type="options.radio? 'radio': 'checkbox'" name ="radiogroup" t-att-checked="options.select_view_id == record.get('id')? true: null"/>
</th>
+ <th t-if="options.isClarkGable" class="oe-record-edit-link" width="1">
+ <img src="/web/static/src/img/pencil.gif" width="12" height="12" class="oe-record-edit-link-img"/>
+ </th>
<t t-foreach="columns" t-as="column">
<t t-set="align" t-value="column.type === 'integer' or column.type == 'float'"/>
<td t-if="!column.meta and column.invisible !== '1'" t-att-title="column.help"
@@ -717,7 +725,7 @@
<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="/web/static/src/img/throbber.gif" width="16" height="16" style="display: none"/>
+ <img t-att-src='_s + "/web/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"
@@ -729,14 +737,14 @@
<br style="clear: both"/>
<ul class="oe-sidebar-attachments-items">
<li t-foreach="attachments" t-as="attachment">
- <t t-if="attachment.type == 'binary'" t-set="attachment.url" t-value="'/web/binary/saveas?session_id='
+ <t t-if="attachment.type == 'binary'" t-set="attachment.url" t-value="_s + '/web/binary/saveas?session_id='
+ session.session_id + '&amp;model=ir.attachment&amp;id=' + attachment.id
+ '&amp;field=datas&amp;fieldname=name&amp;t=' + (new Date().getTime())"/>
<a class="oe-sidebar-attachments-link" t-att-href="attachment.url" target="_blank">
<t t-esc="attachment.name"/>
</a>
<a href="#" class="oe-sidebar-attachment-delete" t-att-data-id="attachment.id" t-attf-title="Delete the attachment #{attachment.name}">
- <img src="/web/static/src/img/attachments-close.png" width="15" height="15" border="0"/>
+ <img t-att-src='_s + "/web/static/src/img/attachments-close.png"' width="15" height="15" border="0"/>
</a>
</li>
</ul>
@@ -888,7 +896,7 @@
t-att-id="widget.element_id"
t-attf-class="field_#{widget.type} #{_(['integer', 'float', 'float_time']).contains(widget.type) ? 'oe-number' : ''}"
style="width: 100%"
- /><img class="oe_field_translate oe_input_icon" t-if="widget.field.translate" src="/web/static/src/img/icons/terp-translate.png" width="16" height="16" border="0"/>
+ /><img class="oe_field_translate oe_input_icon" t-if="widget.field.translate" t-att-src='_s + "/web/static/src/img/icons/terp-translate.png"' width="16" height="16" border="0"/>
</t>
<t t-name="FieldChar.readonly">
<div
@@ -898,7 +906,7 @@
</t>
<t t-name="FieldURI.readonly">
<div>
- <a href="#">#</a>
+ <a href="#" class="oe_form_uri">#</a>
</div>
</t>
<t t-name="FieldEmail">
@@ -909,7 +917,7 @@
</td>
<td width="16">
<button type="button" class="button" title="Send an e-mail with your default e-mail client">
- <img src="/web/static/src/img/icons/terp-mail-message-new.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/terp-mail-message-new.png"'/>
</button>
</td>
</tr>
@@ -923,7 +931,7 @@
</td>
<td width="16">
<button type="button" class="button" title="Open this resource">
- <img src="/web/static/src/img/icons/gtk-ok.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/gtk-ok.png"'/>
</button>
</td>
</tr>
@@ -935,7 +943,7 @@
t-att-id="widget.element_id"
t-attf-class="field_#{widget.type}"
style="width: 100%"
- ></textarea><img class="oe_field_translate oe_input_icon" t-if="widget.field.translate" src="/web/static/src/img/icons/terp-translate.png" width="16" height="16" border="0"/>
+ ></textarea><img class="oe_field_translate oe_input_icon" t-if="widget.field.translate" t-att-src='_s + "/web/static/src/img/icons/terp-translate.png"' width="16" height="16" border="0"/>
</t>
<t t-name="web.datetimepicker">
<div class="oe_datepicker_root">
@@ -943,7 +951,7 @@
<input type="text" size="1" style="width: 100%"
t-att-name="widget.name"
t-attf-class="oe_datepicker_master field_#{widget.type_of_date}"
- /><img class="oe_input_icon oe_datepicker_trigger" src="/web/static/src/img/ui/field_calendar.png"
+ /><img class="oe_input_icon oe_datepicker_trigger" t-att-src='_s + "/web/static/src/img/ui/field_calendar.png"'
title="Select date" width="16" height="16" border="0"/>
</div>
</t>
@@ -963,9 +971,9 @@
<input type="text" size="1" style="width: 100%;"
t-att-id="widget.element_id"/>
<span class="oe-m2o-drop-down-button">
- <img src="/web/static/src/img/down-arrow.png" /></span>
+ <img t-att-src='_s + "/web/static/src/img/down-arrow.png"' /></span>
<span class="oe-m2o-cm-button" t-att-id="widget.name + '_open'">
- <img src="/web/static/src/img/icons/gtk-index.png"/></span>
+ <img t-att-src='_s + "/web/static/src/img/icons/gtk-index.png"'/></span>
<div t-att-id="widget.cm_id" class="contextMenu" style="display:none">
</div>
</div>
@@ -1016,7 +1024,7 @@
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center">
- <img src="/web/static/src/img/placeholder.png" class="oe-binary-image"
+ <img t-att-src='_s + "/web/static/src/img/placeholder.png"' class="oe-binary-image"
t-att-border="widget.readonly ? 0 : 1"
t-att-id="widget.element_id + '_field'"
t-att-name="widget.name"
@@ -1038,7 +1046,7 @@
<input type="hidden" name="session_id" value=""/>
<input type="hidden" name="callback" t-att-value="widget.iframe"/>
<button class="button" type="button" title="Set Image">
- <img src="/web/static/src/img/icons/STOCK_DIRECTORY.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/STOCK_DIRECTORY.png"'/>
</button>
<input type="file" class="oe-binary-file" name="ufile"/>
</form>
@@ -1046,14 +1054,14 @@
</td>
<td>
<button class="button oe-binary-file-clear" type="button" title="Clear">
- <img src="/web/static/src/img/icons/STOCK_MISSING_IMAGE.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/STOCK_MISSING_IMAGE.png"'/>
</button>
</td>
</tr>
</table>
</div>
<div class="oe-binary-progress" style="display: none">
- <img src="/web/static/src/img/throbber.gif" width="16" height="16"/>
+ <img t-att-src='_s + "/web/static/src/img/throbber.gif"' width="16" height="16"/>
<b>Uploading ...</b>
</div>
<iframe t-att-id="widget.iframe" t-att-name="widget.iframe" style="display: none"> </iframe>
@@ -1065,7 +1073,7 @@
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td width="100%">
- <input type="text" size="1"
+ <input type="text" size="1" readonly="readonly"
t-att-name="widget.name"
t-att-id="widget.element_id + '_field'"
t-attf-class="field_#{widget.type}" style="width: 100%"
@@ -1081,7 +1089,7 @@
<input type="hidden" name="session_id" value=""/>
<input type="hidden" name="callback" t-att-value="widget.iframe"/>
<button class="button" type="button" title="Set Image">
- <img src="/web/static/src/img/icons/STOCK_DIRECTORY.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/STOCK_DIRECTORY.png"'/>
<span>Select</span>
</button>
<input type="file" class="oe-binary-file" name="ufile"/>
@@ -1090,13 +1098,13 @@
</td>
<td>
<button class="button oe-binary-file-save" type="button" title="Save As">
- <img src="/web/static/src/img/icons/gtk-save.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/gtk-save.png"'/>
<span>Save As</span>
</button>
</td>
<td>
<button class="button oe-binary-file-clear" type="button" title="Clear">
- <img src="/web/static/src/img/icons/STOCK_MISSING_IMAGE.png"/>
+ <img t-att-src='_s + "/web/static/src/img/icons/STOCK_MISSING_IMAGE.png"'/>
<span>Clear</span>
</button>
</td>
@@ -1104,7 +1112,7 @@
</table>
</td>
<td class="oe-binary-progress" style="display: none" nowrap="true">
- <img src="/web/static/src/img/throbber.gif" width="16" height="16"/>
+ <img t-att-src='_s + "/web/static/src/img/throbber.gif"' width="16" height="16"/>
<b>Uploading ...</b>
<iframe t-att-id="widget.iframe" t-att-name="widget.iframe" style="display: none"> </iframe>
</td>
@@ -1113,7 +1121,7 @@
</t>
<t t-name="WidgetButton">
<button type="button" class="oe_button">
- <img t-if="widget.node.attrs.icon" t-att-src="'/web/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/>
+ <img t-if="widget.node.attrs.icon" t-att-src="_s + '/web/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/>
<span t-if="widget.string"><t t-esc="widget.string"/></span>
</button>
</t>
@@ -1206,7 +1214,7 @@
t-att-title="attrs.help"
t-att-class="classes.join(' ')"
t-att-autofocus="attrs.default_focus === '1' ? 'autofocus' : undefined">
- <img t-att-src="'/web/static/src/img/icons/' + (attrs.icon || 'gtk-home') + '.png'" width="16" height="16"/>
+ <img t-att-src="_s + '/web/static/src/img/icons/' + (attrs.icon || 'gtk-home') + '.png'" width="16" height="16"/>
<br t-if="attrs.string"/>
<t t-esc="attrs.string"/>
</button>
@@ -1353,7 +1361,7 @@
<t t-name="DialogWarning">
<table cellspacing="0" cellpadding="0" border="0" class="oe-dialog-warning">
<tr>
- <td><img src="/web/static/src/img/warning.png" class="oe-dialog-icon"/></td>
+ <td><img t-att-src='_s + "/web/static/src/img/warning.png"' class="oe-dialog-icon"/></td>
<td>
<p>
<t t-js="d">
@@ -1419,6 +1427,7 @@
-->
<t t-jquery="&gt; :first" t-operation="before">
<td t-if="edited and !options.selectable" class="oe-listview-padding"/>
+ <td t-if="edited and !options.isClarkGable" class="oe-listview-padding"/>
</t>
<t t-jquery="&gt; :last" t-operation="after">
<td t-if="edited and !options.deletable" class="oe-listview-padding"/>
@@ -1580,7 +1589,7 @@
<td valign="top" align="left" style="cursor: pointer;" width="18">
<t t-if="field.children">
<t t-if="(field.id).split('/').length != 3">
- <img t-att-id="'parentimg-' + field.id" src="/web/static/src/img/expand.gif" width="16" height="16" border="0"/>
+ <img t-att-id="'parentimg-' + field.id" t-att-src='_s + "/web/static/src/img/expand.gif"' width="16" height="16" border="0"/>
</t>
</t>
</td>
@@ -1696,7 +1705,7 @@
<tr>
<td t-foreach="records[0]" t-as="column">
<input class="sel_fields" placeholder="--- Don't Import ---"/><span class="oe-m2o-drop-down-button">
- <img src="/web/static/src/img/down-arrow.png" /></span>
+ <img t-att-src='_s + "/web/static/src/img/down-arrow.png"' /></span>
</td>
</tr>
<tr t-foreach="records" t-as="record" class="oe_import_grid-row">