diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index 8722fcd2887..c3bf6aff750 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -811,9 +811,8 @@ class Session(openerpweb.Controller):
@openerpweb.jsonrequest
def modules(self, req):
- loaded = module_boot(req)
- modules = module_installed(req)
- return [module for module in modules if module not in loaded]
+ # return all installed modules. Web client is smart enough to not load a module twice
+ return module_installed(req)
@openerpweb.jsonrequest
def eval_domain_and_context(self, req, contexts, domains,
@@ -1142,6 +1141,15 @@ class DataSet(openerpweb.Controller):
def exec_workflow(self, req, model, id, signal):
return req.session.exec_workflow(model, id, signal)
+ @openerpweb.jsonrequest
+ def resequence(self, req, model, ids):
+ m = req.session.model(model)
+ if not len(m.fields_get(['sequence'])):
+ return False
+ for i in range(len(ids)):
+ m.write([ids[i]], { 'sequence': i })
+ return True
+
class DataGroup(openerpweb.Controller):
_cp_path = "/web/group"
@openerpweb.jsonrequest
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css
index 330885de21f..a39838070cb 100644
--- a/addons/web/static/src/css/base.css
+++ b/addons/web/static/src/css/base.css
@@ -1926,9 +1926,9 @@
margin: 8px;
}
.openerp .oe_form_nosheet > header {
- margin-top: -20px;
- margin-left: -20px;
- margin-right: -20px;
+ margin-top: -8px;
+ margin-left: -8px;
+ margin-right: -8px;
}
.openerp .oe_form header {
position: relative;
diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass
index a1726e7e1a9..f1d1f2e9f1f 100644
--- a/addons/web/static/src/css/base.sass
+++ b/addons/web/static/src/css/base.sass
@@ -1487,9 +1487,9 @@ $sheet-max-width: 860px
.oe_form_nosheet
margin: 8px
.oe_form_nosheet > header
- margin-top: -20px
- margin-left: -20px
- margin-right: -20px
+ margin-top: -8px
+ margin-left: -8px
+ margin-right: -8px
// }}}
// FormView.custom tags and classes {{{
.oe_form
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index a36b89400e8..ff066c9f425 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -621,11 +621,11 @@ instance.web.Reload = instance.web.Widget.extend({
},
start: function() {
var l = window.location;
- var timestamp = new Date().getTime();
- var search = "?ts=" + timestamp;
- if (l.search) {
- search = l.search + "&ts=" + timestamp;
- }
+
+ var sobj = $.deparam(l.search.substr(1));
+ sobj.ts = new Date().getTime();
+ var search = '?' + $.param(sobj);
+
var hash = l.hash;
if (this.menu_id) {
hash = "#menu_id=" + this.menu_id;
@@ -948,7 +948,7 @@ instance.web.Client = instance.web.Widget.extend({
instance.web.bus.on('click', this, function(ev) {
$.fn.tipsy.clear();
if (!$(ev.target).is('input[type=file]')) {
- self.$element.find('.oe_dropdown_menu.oe_opened').removeClass('oe_opened');
+ self.$element.find('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened');
}
});
},
diff --git a/addons/web/static/src/js/coresetup.js b/addons/web/static/src/js/coresetup.js
index d5b87d8a81d..229a82a1784 100644
--- a/addons/web/static/src/js/coresetup.js
+++ b/addons/web/static/src/js/coresetup.js
@@ -523,37 +523,50 @@ $.async_when = function() {
/** Setup blockui */
if ($.blockUI) {
$.blockUI.defaults.baseZ = 1100;
- $.blockUI.defaults.message = '
';
+ $.blockUI.defaults.message = '
';
$.blockUI.defaults.css.border = '0';
$.blockUI.defaults.css["background-color"] = '';
- $.blockUI.spinners = [];
}
+
+instance.web.Throbber = instance.web.Widget.extend({
+ template: "Throbber",
+ start: function() {
+ var opts = {
+ lines: 13, // The number of lines to draw
+ length: 7, // The length of each line
+ width: 4, // The line thickness
+ radius: 10, // The radius of the inner circle
+ rotate: 0, // The rotation offset
+ color: '#FFF', // #rgb or #rrggbb
+ speed: 1, // Rounds per second
+ trail: 60, // Afterglow percentage
+ shadow: false, // Whether to render a shadow
+ hwaccel: false, // Whether to use hardware acceleration
+ className: 'spinner', // The CSS class to assign to the spinner
+ zIndex: 2e9, // The z-index (defaults to 2000000000)
+ top: 'auto', // Top position relative to parent in px
+ left: 'auto' // Left position relative to parent in px
+ };
+ this.spin = new Spinner(opts).spin(this.$element[0]);
+ },
+ destroy: function() {
+ if (this.spin)
+ this.spin.stop();
+ this._super();
+ },
+});
+instance.web.Throbber.throbbers = [];
+
instance.web.blockUI = function() {
var tmp = $.blockUI.apply($, arguments);
- var target = $(".oe_blockui_spin")[0];
- var opts = {
- lines: 13, // The number of lines to draw
- length: 7, // The length of each line
- width: 4, // The line thickness
- radius: 10, // The radius of the inner circle
- rotate: 0, // The rotation offset
- color: '#FFF', // #rgb or #rrggbb
- speed: 1, // Rounds per second
- trail: 60, // Afterglow percentage
- shadow: false, // Whether to render a shadow
- hwaccel: false, // Whether to use hardware acceleration
- className: 'spinner', // The CSS class to assign to the spinner
- zIndex: 2e9, // The z-index (defaults to 2000000000)
- top: 'auto', // Top position relative to parent in px
- left: 'auto' // Left position relative to parent in px
- };
- var spinner = new Spinner(opts).spin(target);
- $.blockUI.spinners.push(spinner);
+ var throbber = new instance.web.Throbber();
+ instance.web.Throbber.throbbers.push(throbber);
+ throbber.appendTo($(".oe_blockui_spin_container"));
return tmp;
}
instance.web.unblockUI = function() {
- _.each($.blockUI.spinners, function(el) {
- el.stop();
+ _.each(instance.web.Throbber.throbbers, function(el) {
+ el.destroy();
});
return $.unblockUI.apply($, arguments);
}
diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js
index e360c922918..10fd727e57a 100644
--- a/addons/web/static/src/js/data.js
+++ b/addons/web/static/src/js/data.js
@@ -706,7 +706,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend( /** @lends openerp.
* @returns {$.Deferred}
*/
call_and_eval: function (method, args, domain_index, context_index, callback, error_callback) {
- return this.rpc('/web/dataset/call', {
+ return instance.session.rpc('/web/dataset/call', {
model: this.model,
method: method,
domain_id: domain_index == undefined ? null : domain_index,
@@ -805,6 +805,22 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend( /** @lends openerp.
alter_ids: function(n_ids) {
this.ids = n_ids;
},
+ /**
+ * Resequence records.
+ *
+ * @param {Array} ids identifiers of the records to resequence
+ * @returns {$.Deferred}
+ */
+ resequence: function (ids, options) {
+ options = options || {};
+ return instance.session.rpc('/web/dataset/resequence', {
+ model: this.model,
+ ids: ids,
+ context: this._model.context(options.context),
+ }).pipe(function (results) {
+ return results;
+ });
+ },
});
instance.web.DataSetStatic = instance.web.DataSet.extend({
init: function(parent, model, context, ids) {
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index ef76af3d857..e253cc8da89 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -263,7 +263,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
/**
*
* @param {Object} [options]
- * @param {Boolean} [editable=false] whether the form should be switched to edition mode. A value of ``false`` will keep the current mode.
+ * @param {Boolean} [mode=undefined] If specified, switch the form to specified mode. Can be "edit" or "view".
* @param {Boolean} [reload=true] whether the form should reload its content on show, or use the currently loaded record
* @return {$.Deferred}
*/
@@ -300,9 +300,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
});
}
return shown.pipe(function() {
- if (options.editable) {
- self.to_edit_mode();
- }
+ self._actualize_mode(options.mode || self.options.initial_mode);
self.$element.css({
opacity: '1',
filter: 'alpha(opacity = 100)'
@@ -642,12 +640,21 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this._actualize_mode("edit");
},
/**
- * Reactualize actual_mode.
+ * Ask the view to switch to a precise mode if possible. The view is free to
+ * not respect this command if the state of the dataset is not compatible with
+ * the new mode. For example, it is not possible to switch to edit mode if
+ * the current record is not yet saved in database.
+ *
+ * @param {string} [new_mode] Can be "edit", "view", "create" or undefined. If
+ * undefined the view will test the actual mode to check if it is still consistent
+ * with the dataset state.
*/
_actualize_mode: function(switch_to) {
var mode = switch_to || this.get("actual_mode");
if (! this.datarecord.id) {
mode = "create";
+ } else if (mode === "create") {
+ mode = "edit";
}
this.set({actual_mode: mode});
},
@@ -2724,6 +2731,11 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
this.floating = false;
this.render_value();
});
+ instance.web.bus.on('click', this, function() {
+ if (!this.get("effective_readonly") && this.$input && this.$input.autocomplete('widget').is(':visible')) {
+ this.$input.autocomplete("close");
+ }
+ });
},
initialize_content: function() {
if (!this.get("effective_readonly"))
@@ -2975,10 +2987,12 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
},
_quick_create: function() {
this.no_tipsy = true;
+ this.tip_def.reject();
return instance.web.form.CompletionFieldMixin._quick_create.apply(this, arguments);
},
_search_create_popup: function() {
this.no_tipsy = true;
+ this.tip_def.reject();
return instance.web.form.CompletionFieldMixin._search_create_popup.apply(this, arguments);
},
});
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index 38461c3e905..7068946333b 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -159,7 +159,9 @@ instance.web.ActionManager = instance.web.Widget.extend({
//state = _.extend(this.inner_action.params || {}, state);
}
}
- this.getParent().do_push_state(state);
+ if(!this.dialog) {
+ this.getParent().do_push_state(state);
+ }
}
},
do_load_state: function(state, warm) {
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 614c2a91d79..2d86b40f44f 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -1742,5 +1742,12 @@