summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
authorFabien Meghazi <fme@openerp.com>2014-04-23 14:37:35 +0200
committerFabien Meghazi <fme@openerp.com>2014-04-23 14:37:35 +0200
commitd4b534e7be3586fe17bbb237dd0fd7cdcdb7652c (patch)
tree83ca6d215b4622dc23b6856f4429725c20f0a2ed /addons/web/static/src/js
parentbc1878e3e2d6bb8d76be6f02dfda0d844b5062c8 (diff)
parent8ee8b7bde68a550e2950df75754ad387c8ae13b1 (diff)
[MERGE] upstream
bzr revid: fme@openerp.com-20140423123735-fc38fzp3mtai8xnb
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/chrome.js169
-rw-r--r--addons/web/static/src/js/core.js16
-rw-r--r--addons/web/static/src/js/data_export.js2
-rw-r--r--addons/web/static/src/js/view_form.js253
-rw-r--r--addons/web/static/src/js/view_list.js4
-rw-r--r--addons/web/static/src/js/views.js18
-rw-r--r--addons/web/static/src/js/watch.js58
7 files changed, 350 insertions, 170 deletions
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index 2462617a3d4..4f12a915a7c 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -57,16 +57,6 @@ instance.web.action_warn = function(element, action) {
instance.web.client_actions.add("action_warn", "instance.web.action_warn");
/**
- * The very minimal function everything should call to create a dialog
- * in OpenERP Web Client.
- */
-instance.web.dialog = function(element) {
- var result = element.dialog.apply(element, _.rest(_.toArray(arguments)));
- result.dialog("widget").openerpClass();
- return result;
-};
-
-/**
A useful class to handle dialogs.
Attributes:
@@ -81,6 +71,8 @@ instance.web.Dialog = instance.web.Widget.extend({
@param {Widget} parent
@param {dictionary} options A dictionary that will be forwarded to jQueryUI Dialog. Additionaly, that
dictionary can contain the following keys:
+ - size: one of the following: 'large', 'medium', 'small'
+ - dialogClass: class to add to the body of dialog
- buttons: Deprecated. The buttons key is not propagated to jQueryUI Dialog. It must be a dictionary (key = button
label, value = click handler) or a list of dictionaries (each element in the dictionary is send to the
corresponding method of a jQuery element targeting the <button> tag). It is deprecated because all dialogs
@@ -94,57 +86,15 @@ instance.web.Dialog = instance.web.Widget.extend({
this._super(parent);
this.content_to_set = content;
this.dialog_options = {
- modal: true,
destroy_on_close: true,
- width: 900,
- min_width: 0,
- max_width: '95%',
- height: 'auto',
- min_height: 0,
- max_height: $(window.top).height() - 200,
- autoOpen: false,
- position: [false, 40],
+ size: 'large', //'medium', 'small'
buttons: null,
- resizeStop: function() {
- self.trigger("resized");
- },
};
if (options) {
_.extend(this.dialog_options, options);
}
this.on("closing", this, this._closing);
- this.$buttons = $('<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"><span class="oe_dialog_custom_buttons"/></div>');
- },
- _get_options: function() {
- var self = this;
- var o = _.extend({}, this.dialog_options);
- var sizes = {
- width: $(window.top).width(),
- height: $(window.top).height(),
- };
- _.each(sizes, function(available_size, unit) {
- o[unit] = self._get_size(o[unit], available_size);
- o['min_' + unit] = self._get_size(o['min_' + unit] || 0, available_size);
- o['max_' + unit] = self._get_size(o['max_' + unit] || 0, available_size);
- if (o[unit] !== 'auto' && o['min_' + unit] && o[unit] < o['min_' + unit]) {
- o[unit] = o['min_' + unit];
- }
- if (o[unit] !== 'auto' && o['max_' + unit] && o[unit] > o['max_' + unit]) {
- o[unit] = o['max_' + unit];
- }
- });
- o.title = o.title || this.dialog_title;
- return o;
- },
- _get_size: function(val, available_size) {
- val = val.toString();
- if (val === 'auto') {
- return val;
- } else if (val.slice(-1) === "%") {
- return Math.round(available_size / 100 * parseInt(val.slice(0, -1), 10));
- } else {
- return parseInt(val, 10);
- }
+ this.$buttons = $('<div class="modal-footer"><span class="oe_dialog_custom_buttons"/></div>');
},
renderElement: function() {
if (this.content_to_set) {
@@ -162,8 +112,7 @@ instance.web.Dialog = instance.web.Widget.extend({
if (!this.dialog_inited) {
this.init_dialog();
}
- this.$el.dialog('open');
- this.$el.dialog("widget").append(this.$buttons);
+ this.$buttons.insertAfter(this.$dialog_box.find(".modal-body"));
return this;
},
_add_buttons: function(buttons) {
@@ -188,16 +137,39 @@ instance.web.Dialog = instance.web.Widget.extend({
@return The result returned by start().
*/
init_dialog: function() {
- var options = this._get_options();
+ var self = this;
+ var options = _.extend({}, this.dialog_options);
+ options.title = options.title || this.dialog_title;
if (options.buttons) {
this._add_buttons(options.buttons);
delete(options.buttons);
}
this.renderElement();
- instance.web.dialog(this.$el, options);
- if (options.height === 'auto' && options.max_height) {
- this.$el.css({ 'max-height': options.max_height, 'overflow-y': 'auto' });
+
+ this.$dialog_box = $(QWeb.render('Dialog', options)).appendTo("body");
+ this.$el.modal({
+ 'backdrop': false,
+ 'keyboard': true,
+ });
+ if (options.size !== 'large'){
+ var dialog_class_size = this.$dialog_box.find('.modal-lg').removeClass('modal-lg')
+ if (options.size === 'small'){
+ dialog_class_size.addClass('modal-sm');
+ }
}
+
+ this.$el.appendTo(this.$dialog_box.find(".modal-body"));
+ var $dialog_content = this.$dialog_box.find('.modal-content');
+ if (options.dialogClass){
+ $dialog_content.find(".modal-body").addClass(options.dialogClass);
+ }
+ $dialog_content.openerpClass();
+
+ this.$dialog_box.on('hidden.bs.modal', this, function(){
+ self.close();
+ });
+ this.$dialog_box.modal('show');
+
this.dialog_inited = true;
var res = this.start();
return res;
@@ -206,9 +178,11 @@ instance.web.Dialog = instance.web.Widget.extend({
Closes the popup, if destroy_on_close was passed to the constructor, it is also destroyed.
*/
close: function(reason) {
- if (this.dialog_inited && this.$el.is(":data(dialog)")) {
+ if (this.dialog_inited) {
this.trigger("closing", reason);
- this.$el.dialog('close');
+ if (this.$el.is(":data(bs.modal)")) { // may have been destroyed by closing signal
+ this.$el.parents('.modal').modal('hide');
+ }
}
},
_closing: function() {
@@ -225,6 +199,7 @@ instance.web.Dialog = instance.web.Widget.extend({
*/
destroy: function (reason) {
this.$buttons.remove();
+ var self = this;
_.each(this.getChildren(), function(el) {
el.destroy();
});
@@ -233,8 +208,14 @@ instance.web.Dialog = instance.web.Widget.extend({
this.close(reason);
this.__tmp_dialog_destroying = undefined;
}
- if (this.dialog_inited && !this.isDestroyed() && this.$el.is(":data(dialog)")) {
- this.$el.dialog('destroy');
+ if (this.dialog_inited && !this.isDestroyed() && this.$el.is(":data(bs.modal)")) {
+ //we need this to put the instruction to remove modal from DOM at the end
+ //of the queue, otherwise it might already have been removed before the modal-backdrop
+ //is removed when pressing escape key
+ var $parent = this.$el.parents('.modal');
+ setTimeout(function () {
+ $parent.remove();
+ },0);
}
this._super();
}
@@ -272,12 +253,13 @@ instance.web.CrashManager = instance.web.Class.extend({
if (error.data.exception_type === "except_osv") {
error = _.extend({}, error, {data: _.extend({}, error.data, {message: error.data.arguments[0] + "\n\n" + error.data.arguments[1]})});
}
- instance.web.dialog($('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>'), {
+ new instance.web.Dialog(this, {
+ size: 'medium',
title: "OpenERP " + (_.str.capitalize(error.type) || "Warning"),
buttons: [
- {text: _t("Ok"), click: function() { $(this).dialog("close"); }}
- ]
- });
+ {text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
+ ],
+ }, $('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>')).open();
},
show_error: function(error) {
if (!this.active) {
@@ -285,17 +267,12 @@ instance.web.CrashManager = instance.web.Class.extend({
}
var buttons = {};
buttons[_t("Ok")] = function() {
- $(this).dialog("close");
+ this.parents('.modal').modal('hide');
};
- var dialog = new instance.web.Dialog(this, {
+ new instance.web.Dialog(this, {
title: "OpenERP " + _.str.capitalize(error.type),
- width: '80%',
- height: '50%',
- min_width: '800px',
- min_height: '600px',
buttons: buttons
- }).open();
- dialog.$el.html(QWeb.render('CrashManager.error', {session: instance.session, error: error}));
+ }, QWeb.render('CrashManager.error', {session: instance.session, error: error})).open();
},
show_message: function(exception) {
this.show_error({
@@ -342,16 +319,17 @@ instance.web.RedirectWarningHandler = instance.web.Dialog.extend(instance.web.Ex
error = this.error;
error.data.message = error.data.arguments[0];
- instance.web.dialog($('<div>' + QWeb.render('CrashManager.warning', {error: error}) + '</div>'), {
+ new instance.web.Dialog(this, {
+ size: 'medium',
title: "OpenERP " + (_.str.capitalize(error.type) || "Warning"),
buttons: [
- {text: _t("Ok"), click: function() { $(this).dialog("close"); }},
+ {text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }},
{text: error.data.arguments[2], click: function() {
window.location.href='#action='+error.data.arguments[1];
- $(this).dialog("close");
+ this.$el.parents('.modal').modal('hide');
}}
- ]
- });
+ ],
+ }, QWeb.render('CrashManager.warning', {error: error})).open();
this.destroy();
}
});
@@ -498,13 +476,13 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
* @param {String} error.error message of the error dialog
*/
display_error: function (error) {
- return instance.web.dialog($('<div>'), {
- modal: true,
+ return new instance.web.Dialog(this, {
+ size: 'medium',
title: error.title,
buttons: [
- {text: _t("Ok"), click: function() { $(this).dialog("close"); }}
+ {text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }}
]
- }).html(error.error);
+ }, $('<div>').html(error.error)).open();
},
do_create: function(form) {
var self = this;
@@ -731,13 +709,13 @@ instance.web.ChangePassword = instance.web.Widget.extend({
});
},
display_error: function (error) {
- return instance.web.dialog($('<div>'), {
- modal: true,
+ return new instance.web.Dialog(this, {
+ size: 'medium',
title: error.title,
buttons: [
- {text: _t("Ok"), click: function() { $(this).dialog("close"); }}
+ {text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }}
]
- }).html(error.error);
+ }, $('<div>').html(error.error)).open();
},
});
instance.web.client_actions.add("change_password", "instance.web.ChangePassword");
@@ -1052,8 +1030,11 @@ instance.web.UserMenu = instance.web.Widget.extend({
e.preventDefault();
window.location = $.param.querystring( window.location.href, 'debug');
});
- instance.web.dialog($help, {autoOpen: true,
- modal: true, width: 507, height: 290, resizable: false, title: _t("About")});
+ new instance.web.Dialog(this, {
+ size: 'medium',
+ dialogClass: 'oe_act_window',
+ title: _t("About"),
+ }, $help).open();
});
},
});
@@ -1097,8 +1078,8 @@ instance.web.Client = instance.web.Widget.extend({
},
bind_events: function() {
var self = this;
- this.$el.on('mouseenter', '.oe_systray > div:not([data-tipsy=true])', function() {
- $(this).attr('data-tipsy', 'true').tipsy().trigger('mouseenter');
+ this.$el.on('mouseenter', '.oe_systray > div:not([data-toggle=tooltip])', function() {
+ $(this).attr('data-toggle', 'tooltip').tooltip().trigger('mouseenter');
});
this.$el.on('click', '.oe_dropdown_toggle', function(ev) {
ev.preventDefault();
@@ -1122,7 +1103,7 @@ instance.web.Client = instance.web.Widget.extend({
}, 0);
});
instance.web.bus.on('click', this, function(ev) {
- $.fn.tipsy.clear();
+ $.fn.tooltip('destroy');
if (!$(ev.target).is('input[type=file]')) {
self.$el.find('.oe_dropdown_menu.oe_opened, .oe_dropdown_toggle.oe_opened').removeClass('oe_opened');
}
diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js
index 90c84ba9cda..a4bcd1922de 100644
--- a/addons/web/static/src/js/core.js
+++ b/addons/web/static/src/js/core.js
@@ -788,6 +788,22 @@ instance.web.unblockUI = function() {
return $.unblockUI.apply($, arguments);
};
+
+/* Bootstrap defaults overwrite */
+$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top';
+$.fn.tooltip.Constructor.DEFAULTS.html = true;
+$.fn.tooltip.Constructor.DEFAULTS.container = 'body';
+//overwrite bootstrap tooltip method to fix bug when using placement
+//auto and the parent element does not exist anymore resulting in
+//an error. This should be remove once bootstrap fix the bug
+var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show;
+$.fn.tooltip.Constructor.prototype.show = function (e) {
+ if (this.$element.parent().length === 0){
+ return;
+ }
+ return bootstrap_show_function.call(this, e);
+};
+
/**
* Registry for all the client actions key: tag value: widget
*/
diff --git a/addons/web/static/src/js/data_export.js b/addons/web/static/src/js/data_export.js
index 252a5a378cc..2de933f45e8 100644
--- a/addons/web/static/src/js/data_export.js
+++ b/addons/web/static/src/js/data_export.js
@@ -46,7 +46,6 @@ instance.web.DataExport = instance.web.Dialog.extend({
start: function() {
var self = this;
this._super.apply(this, arguments);
- self.$el.removeClass('ui-dialog-content ui-widget-content');
var got_fields = new $.Deferred();
this.$el.find('#import_compat').change(function() {
@@ -413,7 +412,6 @@ instance.web.DataExport = instance.web.Dialog.extend({
});
},
close: function() {
- this.$el.remove();
this._super();
}
});
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 37c60a36f04..21a34db0036 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -586,13 +586,13 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this._internal_set_values(result.value, processed);
}
if (!_.isEmpty(result.warning)) {
- instance.web.dialog($(QWeb.render("CrashManager.warning", result.warning)), {
+ new instance.web.Dialog(this, {
+ size: 'medium',
title:result.warning.title,
- modal: true,
buttons: [
- {text: _t("Ok"), click: function() { $(this).dialog("close"); }}
+ {text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
]
- });
+ }, QWeb.render("CrashManager.warning", result.warning)).open();
}
return $.Deferred().resolve();
@@ -631,6 +631,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
});
}
return $.when();
+ }).fail(function() {
+ self.save_list.pop();
+ return $.when();
});
}
return iterate();
@@ -727,8 +730,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
}
}
},
- on_button_save: function() {
+ on_button_save: function(e) {
var self = this;
+ $(e.target).attr("disabled", true);
return this.save().done(function(result) {
self.trigger("save", result);
self.reload().then(function() {
@@ -738,6 +742,8 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
parent.menu.do_reload_needaction();
}
});
+ }).always(function(){
+ $(e.target).attr("disabled", false);
});
},
on_button_cancel: function(event) {
@@ -1080,7 +1086,6 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
};
})
.value();
-
var d = new instance.web.Dialog(this, {
title: _t("Set Default"),
args: {
@@ -1833,7 +1838,7 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
this.$el.addClass(this.node.attrs["class"] || "");
},
destroy: function() {
- $.fn.tipsy.clear();
+ $.fn.tooltip('destroy');
this._super.apply(this, arguments);
},
/**
@@ -1864,10 +1869,17 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
do_attach_tooltip: function(widget, trigger, options) {
widget = widget || this;
trigger = trigger || this.$el;
+ var container = 'body';
+ //in the case we have a modal currently showing, attach tooltip
+ //to the modal to prevent the tooltip to show in the body in the
+ //case we close the modal too fast
+ if (window.$('.modal.in').length>0){
+ container = window.$('.modal.in:last()');
+ }
options = _.extend({
- delayIn: 500,
- delayOut: 0,
- fade: true,
+ delay: { show: 500, hide: 0 },
+ trigger: 'hover',
+ container: container,
title: function() {
var template = widget.template + '.tooltip';
if (!QWeb.has_template(template)) {
@@ -1878,12 +1890,12 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
widget: widget
});
},
- gravity: $.fn.tipsy.autoBounds(50, 'nw'),
- html: true,
- opacity: 0.85,
- trigger: 'hover'
}, options || {});
- $(trigger).tipsy(options);
+ //only show tooltip if we are in debug or if we have a help to show, otherwise it will display
+ //as empty
+ if (instance.session.debug || widget.node.attrs.help || (widget.field && widget.field.help)){
+ $(trigger).tooltip(options);
+ }
},
/**
* Builds a new context usable for operations related to fields by merging
@@ -1956,26 +1968,23 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({
var exec_action = function() {
if (self.node.attrs.confirm) {
var def = $.Deferred();
- var dialog = instance.web.dialog($('<div/>').text(self.node.attrs.confirm), {
+ var dialog = new instance.web.Dialog(this, {
title: _t('Confirm'),
- modal: true,
buttons: [
{text: _t("Cancel"), click: function() {
- $(this).dialog("close");
+ this.parents('.modal').modal('hide');
}
},
{text: _t("Ok"), click: function() {
var self2 = this;
self.on_confirmed().always(function() {
- $(self2).dialog("close");
+ self2.parents('.modal').modal('hide');
});
}
}
],
- beforeClose: function() {
- def.resolve();
- },
- });
+ }, $('<div/>').text(self.node.attrs.confirm)).open();
+ dialog.on("closing", null, function() {def.resolve();});
return def.promise();
} else {
return self.on_confirmed();
@@ -2123,8 +2132,8 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w
this.$el.find('.oe_field_translate').click(this.on_translate);
}
this.$label = this.view ? this.view.$el.find('label[for=' + this.id_for_label + ']') : $();
+ this.do_attach_tooltip(this, this.$label[0] || this.$el);
if (instance.session.debug) {
- this.do_attach_tooltip(this, this.$label[0] || this.$el);
this.$label.off('dblclick').on('dblclick', function() {
console.log("Field '%s' of type '%s' in View: %o", self.name, (self.node.attrs.widget || self.field.type), self.view);
window.w = self;
@@ -2439,6 +2448,76 @@ instance.web.form.FieldFloat = instance.web.form.FieldChar.extend({
}
});
+instance.web.form.FieldCharDomain = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
+ init: function(field_manager, node) {
+ this._super.apply(this, arguments);
+ },
+ start: function() {
+ var self = this;
+ this._super.apply(this, arguments);
+ this.on("change:effective_readonly", this, function () {
+ this.display_field();
+ this.render_value();
+ });
+ this.display_field();
+ return this._super();
+ },
+ render_value: function() {
+ this.$('button.select_records').css('visibility', this.get('effective_readonly') ? 'hidden': '');
+ },
+ set_value: function(value_) {
+ var self = this;
+ this.set('value', value_ || false);
+ this.display_field();
+ },
+ display_field: function() {
+ var self = this;
+ this.$el.html(instance.web.qweb.render("FieldCharDomain", {widget: this}));
+ if (this.get('value')) {
+ var model = this.options.model || this.field_manager.get_field_value(this.options.model_field);
+ var domain = instance.web.pyeval.eval('domain', this.get('value'));
+ var ds = new instance.web.DataSetStatic(self, model, self.build_context());
+ ds.call('search_count', [domain]).then(function (results) {
+ $('.oe_domain_count', self.$el).text(results + ' records selected');
+ $('button span', self.$el).text(' Change selection');
+ });
+ } else {
+ $('.oe_domain_count', this.$el).text('0 record selected');
+ $('button span', this.$el).text(' Select records');
+ };
+ this.$('.select_records').on('click', self.on_click);
+ },
+ on_click: function(ev) {
+ var self = this;
+ var model = this.options.model || this.field_manager.get_field_value(this.options.model_field);
+ this.pop = new instance.web.form.SelectCreatePopup(this);
+ this.pop.select_element(
+ model, {title: 'Select records...'},
+ [], this.build_context());
+ this.pop.on("elements_selected", self, function(element_ids) {
+ if (this.pop.$('input.oe_list_record_selector').prop('checked')) {
+ var search_data = this.pop.searchview.build_search_data();
+ var domain_done = instance.web.pyeval.eval_domains_and_contexts({
+ domains: search_data.domains,
+ contexts: search_data.contexts,
+ group_by_seq: search_data.groupbys || []
+ }).then(function (results) {
+ return results.domain;
+ });
+ }
+ else {
+ var domain = ["id", "in", element_ids];
+ var domain_done = $.Deferred().resolve(domain);
+ }
+ $.when(domain_done).then(function (domain) {
+ var domain = self.pop.dataset.domain.concat(domain || []);
+ self.set_value(JSON.stringify(domain))
+ });
+ });
+ event.preventDefault();
+ },
+});
+
instance.web.DateTimeWidget = instance.web.Widget.extend({
template: "web.datepicker",
jqueryui_object: 'datetimepicker',
@@ -2834,10 +2913,10 @@ instance.web.form.FieldPercentPie = instance.web.form.AbstractField.extend({
svg.innerHTML = "";
nv.addGraph(function() {
- var size=43;
+ var width = 42, height = 42;
var chart = nv.models.pieChart()
- .width(size)
- .height(size)
+ .width(width)
+ .height(height)
.margin({top: 0, right: 0, bottom: 0, left: 0})
.donut(true)
.showLegend(false)
@@ -2850,11 +2929,11 @@ instance.web.form.FieldPercentPie = instance.web.form.AbstractField.extend({
.datum([{'x': 'value', 'y': value}, {'x': 'complement', 'y': 100 - value}])
.transition()
.call(chart)
- .attr({width:size, height:size});
+ .attr('style', 'width: ' + width + 'px; height:' + height + 'px;');
d3.select(svg)
.append("text")
- .attr({x: size/2, y: size/2 + 3, 'text-anchor': 'middle'})
+ .attr({x: width/2, y: height/2 + 3, 'text-anchor': 'middle'})
.style({"font-size": "10px", "font-weight": "bold"})
.text(formatted_value);
@@ -2864,6 +2943,43 @@ instance.web.form.FieldPercentPie = instance.web.form.AbstractField.extend({
}
});
+/**
+ The FieldBarChart expectsa list of values (indeed)
+*/
+instance.web.form.FieldBarChart = instance.web.form.AbstractField.extend({
+ template: 'FieldBarChart',
+
+ render_value: function() {
+ var value = JSON.parse(this.get('value'));
+ var svg = this.$('svg')[0];
+ svg.innerHTML = "";
+ nv.addGraph(function() {
+ var width = 34, height = 34;
+ var chart = nv.models.discreteBarChart()
+ .x(function (d) { return d.tooltip })
+ .y(function (d) { return d.value })
+ .width(width)
+ .height(height)
+ .margin({top: 0, right: 0, bottom: 0, left: 0})
+ .tooltips(false)
+ .showValues(false)
+ .transitionDuration(350)
+ .showXAxis(false)
+ .showYAxis(false);
+
+ d3.select(svg)
+ .datum([{key: 'values', values: value}])
+ .transition()
+ .call(chart)
+ .attr('style', 'width: ' + (width + 4) + 'px; height: ' + (height + 8) + 'px;');
+
+ nv.utils.windowResize(chart.update);
+
+ return chart;
+ });
+
+ }
+});
instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
@@ -3234,7 +3350,7 @@ instance.web.form.M2ODialog = instance.web.Dialog.extend({
init: function(parent) {
this._super(parent, {
title: _.str.sprintf(_t("Add %s"), parent.string),
- width: 312,
+ size: 'medium',
});
},
start: function() {
@@ -3302,7 +3418,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
delete this.$drop_down;
}
if (this.$input) {
- this.$input.closest(".ui-dialog .ui-dialog-content").off('scroll');
+ this.$input.closest(".modal .modal-content").off('scroll');
this.$input.off('keyup blur autocompleteclose autocompleteopen ' +
'focus focusout change keydown');
delete this.$input;
@@ -3345,20 +3461,25 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
return;
}
var pop = new instance.web.form.FormOpenPopup(self);
- pop.show_element(
- self.field.relation,
- self.get("value"),
- self.build_context(),
- {
- title: _t("Open: ") + self.string
- }
- );
- pop.on('write_completed', self, function(){
- self.display_value = {};
- self.display_value_backup = {};
- self.render_value();
- self.focus();
- self.view.do_onchange(self);
+ var context = self.build_context().eval();
+ var model_obj = new instance.web.Model(self.field.relation);
+ model_obj.call('get_formview_id', [self.get("value"), context]).then(function(view_id){
+ pop.show_element(
+ self.field.relation,
+ self.get("value"),
+ self.build_context(),
+ {
+ title: _t("Open: ") + self.string,
+ view_id: view_id
+ }
+ );
+ pop.on('write_completed', self, function(){
+ self.display_value = {};
+ self.display_value_backup = {};
+ self.render_value();
+ self.focus();
+ self.view.do_onchange(self);
+ });
});
});
@@ -3395,7 +3516,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
self.$input.autocomplete("close");
}
}, 50);
- this.$input.closest(".ui-dialog .ui-dialog-content").on('scroll', this, close_autocomplete);
+ this.$input.closest(".modal .modal-content").on('scroll', this, close_autocomplete);
self.ed_def = $.Deferred();
self.uned_def = $.Deferred();
@@ -3420,7 +3541,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
}
self.floating = false;
}
- if (used && self.get("value") === false && ! self.no_ed) {
+ if (used && self.get("value") === false && ! self.no_ed && (self.options.no_create === false || self.options.no_create === undefined)) {
self.ed_def.reject();
self.uned_def.reject();
self.ed_def = $.Deferred();
@@ -3554,13 +3675,10 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
.html(link);
if (! this.options.no_open)
$link.click(function () {
- self.do_action({
- type: 'ir.actions.act_window',
- res_model: self.field.relation,
- res_id: self.get("value"),
- views: [[false, 'form']],
- target: 'current',
- context: self.build_context().eval(),
+ var context = self.build_context().eval();
+ var model_obj = new instance.web.Model(self.field.relation);
+ model_obj.call('get_formview_action', [self.get("value"), context]).then(function(action){
+ self.do_action(action);
});
return false;
});
@@ -4921,13 +5039,12 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({
var self = this;
this.renderElement();
var dialog = new instance.web.Dialog(this, {
- min_width: '800px',
dialogClass: 'oe_act_window',
- close: function() {
- self.check_exit(true);
- },
title: this.options.title || "",
}, this.$el).open();
+ dialog.on('closing', this, function (e){
+ self.check_exit(true);
+ });
this.$buttonpane = dialog.$buttons;
this.start();
},
@@ -4994,8 +5111,8 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({
},
destroy: function () {
this.trigger('closed');
- if (this.$el.is(":data(dialog)")) {
- this.$el.dialog('close');
+ if (this.$el.is(":data(bs.modal)")) {
+ this.$el.parents('.modal').modal('hide');
}
this._super();
},
@@ -5921,20 +6038,30 @@ instance.web.form.X2ManyCounter = instance.web.form.AbstractField.extend(instanc
display a simple string "<value of field> <label of the field>"
*/
instance.web.form.StatInfo = instance.web.form.AbstractField.extend({
+ is_field_number: true,
init: function() {
this._super.apply(this, arguments);
- this.set("value", 0);
+ this.internal_set_value(0);
+ },
+ set_value: function(value_) {
+ if (value_ === false || value_ === undefined) {
+ value_ = 0;
+ }
+ this._super.apply(this, [value_]);
},
render_value: function() {
var options = {
value: this.get("value") || 0,
- text: this.string,
};
+ if (! this.node.attrs.nolabel) {
+ options.text = this.string
+ }
this.$el.html(QWeb.render("StatInfo", options));
},
});
+
/**
* Registry of form fields, called by :js:`instance.web.FormView`.
*
@@ -5948,6 +6075,7 @@ instance.web.form.widgets = new instance.web.Registry({
'url' : 'instance.web.form.FieldUrl',
'text' : 'instance.web.form.FieldText',
'html' : 'instance.web.form.FieldTextHtml',
+ 'char_domain': 'instance.web.form.FieldCharDomain',
'date' : 'instance.web.form.FieldDate',
'datetime' : 'instance.web.form.FieldDatetime',
'selection' : 'instance.web.form.FieldSelection',
@@ -5963,6 +6091,7 @@ instance.web.form.widgets = new instance.web.Registry({
'boolean' : 'instance.web.form.FieldBoolean',
'float' : 'instance.web.form.FieldFloat',
'percentpie': 'instance.web.form.FieldPercentPie',
+ 'barchart': 'instance.web.form.FieldBarChart',
'integer': 'instance.web.form.FieldFloat',
'float_time': 'instance.web.form.FieldFloat',
'progressbar': 'instance.web.form.FieldProgressBar',
diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js
index cdb9ff8302f..16d0310ab4d 100644
--- a/addons/web/static/src/js/view_list.js
+++ b/addons/web/static/src/js/view_list.js
@@ -2261,8 +2261,8 @@ instance.web.list.Button = instance.web.list.Column.extend({
attrs = this.modifiers_for(row_data);
}
if (attrs.invisible) { return ''; }
-
- return QWeb.render('ListView.row.button', {
+ var template = this.icon && 'ListView.row.button' || 'ListView.row.text_button';
+ return QWeb.render(template, {
widget: this,
prefix: instance.session.prefix,
disabled: attrs.readonly
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index 2f401445f7e..b9015f6b311 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -410,10 +410,10 @@ instance.web.ActionManager = instance.web.Widget.extend({
}
this.dialog_stop(executor.action);
this.dialog = new instance.web.Dialog(this, {
+ title: executor.action.name,
dialogClass: executor.klass,
});
this.dialog.on("closing", null, options.on_close);
- this.dialog.dialog_title = executor.action.name;
if (widget instanceof instance.web.ViewManager) {
_.extend(widget.flags, {
$buttons: this.dialog.$buttons,
@@ -581,7 +581,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
var self = this;
this.$el.find('.oe_view_manager_switch a').click(function() {
self.switch_mode($(this).data('view-type'));
- }).tipsy();
+ }).tooltip();
var views_ids = {};
_.each(this.views_src, function(view) {
self.views[view.view_type] = $.extend({}, view, {
@@ -926,7 +926,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
current_view = this.views[this.active_view].controller;
switch (val) {
case 'fvg':
- var dialog = new instance.web.Dialog(this, { title: _t("Fields View Get"), width: '95%' }).open();
+ var dialog = new instance.web.Dialog(this, { title: _t("Fields View Get") }).open();
$('<pre>').text(instance.web.json_node_to_xml(current_view.fields_view.arch, true)).appendTo(dialog.$el);
break;
case 'tests':
@@ -943,7 +943,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
this.dataset.call('perm_read', [ids]).done(function(result) {
var dialog = new instance.web.Dialog(this, {
title: _.str.sprintf(_t("View Log (%s)"), self.dataset.model),
- width: 400
+ size: 'medium',
}, QWeb.render('ViewManagerDebugViewLog', {
perm : result[0],
format : instance.web.format_value
@@ -986,7 +986,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
new instance.web.Dialog(self, {
title: _.str.sprintf(_t("Model %s fields"),
self.dataset.model),
- width: '95%'}, $root).open();
+ }, $root).open();
});
break;
case 'edit_workflow':
@@ -1157,10 +1157,8 @@ instance.web.Sidebar = instance.web.Widget.extend({
this.$('.oe_form_dropdown_section').each(function() {
$(this).toggle(!!$(this).find('li').length);
});
-
- self.$("[title]").tipsy({
- 'html': true,
- 'delayIn': 500,
+ self.$("[title]").tooltip({
+ delay: { show: 500, hide: 0}
});
},
/**
@@ -1223,7 +1221,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
domain = $.Deferred().resolve(undefined);
}
if (ids.length === 0) {
- instance.web.dialog($("<div />").text(_t("You must choose at least one record.")), { title: _t("Warning"), modal: true });
+ new instance.web.Dialog(this, { title: _t("Warning"), size: 'medium',}, $("<div />").text(_t("You must choose at least one record."))).open();
return false;
}
var active_ids_context = {
diff --git a/addons/web/static/src/js/watch.js b/addons/web/static/src/js/watch.js
new file mode 100644
index 00000000000..efa80a1d529
--- /dev/null
+++ b/addons/web/static/src/js/watch.js
@@ -0,0 +1,58 @@
+(function() {
+/*
+ * object.watch polyfill
+ *
+ * 2012-04-03
+ *
+ * By Eli Grey, http://eligrey.com
+ * Public Domain.
+ * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+ */
+
+// object.watch
+if (!Object.prototype.watch) {
+ Object.defineProperty(Object.prototype, "watch", {
+ enumerable: false
+ , configurable: true
+ , writable: false
+ , value: function (prop, handler) {
+ var
+ oldval = this[prop]
+ , newval = oldval
+ , getter = function () {
+ return newval;
+ }
+ , setter = function (val) {
+ oldval = newval;
+ return newval = handler.call(this, prop, oldval, val);
+ }
+ ;
+
+ if (delete this[prop]) { // can't watch constants
+ Object.defineProperty(this, prop, {
+ get: getter
+ , set: setter
+ , enumerable: true
+ , configurable: true
+ });
+ }
+ }
+ });
+}
+
+// object.unwatch
+if (!Object.prototype.unwatch) {
+ Object.defineProperty(Object.prototype, "unwatch", {
+ enumerable: false
+ , configurable: true
+ , writable: false
+ , value: function (prop) {
+ var val = this[prop];
+ delete this[prop]; // remove accessors
+ this[prop] = val;
+ }
+ });
+}
+
+})();
+