summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/view_form.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src/js/view_form.js')
-rw-r--r--addons/web/static/src/js/view_form.js253
1 files changed, 191 insertions, 62 deletions
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',