this.fields_order = [];
this.datarecord = {};
this._onchange_specs = {};
- this.onchanges_defs = [];
+ this.onchanges_mutex = new $.Mutex();
this.default_focus_field = null;
this.default_focus_button = null;
this.fields_registry = instance.web.form.widgets;
def = self.alive(new instance.web.Model(self.dataset.model).call(
"onchange", [ids, values, trigger_field_name, onchange_specs, context]));
}
- var onchange_def = def.then(function(response) {
- if (widget && widget.field['change_default']) {
- var fieldname = widget.name;
- var value_;
- if (response.value && (fieldname in response.value)) {
- // Use value from onchange if onchange executed
- value_ = response.value[fieldname];
- } else {
- // otherwise get form value for field
- value_ = self.fields[fieldname].get_value();
- }
- var condition = fieldname + '=' + value_;
-
- if (value_) {
- return self.alive(new instance.web.Model('ir.values').call(
- 'get_defaults', [self.model, condition]
- )).then(function (results) {
- if (!results.length) {
+ this.onchanges_mutex.exec(function(){
+ return def.then(function(response) {
+ if (widget && widget.field['change_default']) {
+ var fieldname = widget.name;
+ var value_;
+ if (response.value && (fieldname in response.value)) {
+ // Use value from onchange if onchange executed
+ value_ = response.value[fieldname];
+ } else {
+ // otherwise get form value for field
+ value_ = self.fields[fieldname].get_value();
+ }
+ var condition = fieldname + '=' + value_;
+
+ if (value_) {
+ return self.alive(new instance.web.Model('ir.values').call(
+ 'get_defaults', [self.model, condition]
+ )).then(function (results) {
+ if (!results.length) {
+ return response;
+ }
+ if (!response.value) {
+ response.value = {};
+ }
+ for(var i=0; i<results.length; ++i) {
+ // [whatever, key, value]
+ var triplet = results[i];
+ response.value[triplet[1]] = triplet[2];
+ }
return response;
- }
- if (!response.value) {
- response.value = {};
- }
- for(var i=0; i<results.length; ++i) {
- // [whatever, key, value]
- var triplet = results[i];
- response.value[triplet[1]] = triplet[2];
- }
- return response;
- });
+ });
+ }
}
- }
- return response;
- }).then(function(response) {
- return self.on_processed_onchange(response);
+ return response;
+ }).then(function(response) {
+ return self.on_processed_onchange(response);
+ });
});
- this.onchanges_defs.push(onchange_def);
- return onchange_def;
+ return this.onchanges_mutex.def;
} catch(e) {
console.error(e);
instance.webclient.crashmanager.show_message(e);
var self = this;
return this.mutating_mutex.exec(function() {
function iterate() {
- var start = $.Deferred();
- start.resolve();
- start = _.reduce(self.onchanges_defs, function(memo, d){
- return memo.then(function(){
- return d;
- }, function(){
- return d;
- });
- }, start);
- var defs = [start];
+
+ var mutex = new $.Mutex();
_.each(self.fields, function(field) {
- defs.push(field.commit_value());
+ self.onchanges_mutex.def.then(function(){
+ mutex.exec(function(){
+ return field.commit_value();
+ });
+ });
});
+
var args = _.toArray(arguments);
- return $.when.apply($, defs).then(function() {
+ return $.when.apply(null, [mutex.def, self.onchanges_mutex.def]).then(function() {
var save_obj = self.save_list.pop();
if (save_obj) {
return self._process_save(save_obj).then(function() {
* if the current record is not yet saved. It will then stay in create mode.
*/
to_edit_mode: function() {
- this.onchanges_defs = [];
+ this.onchanges_mutex = new $.Mutex();
this._actualize_mode("edit");
},
/**
init: function (field_manager, node) {
this._super(field_manager, node);
},
+ start: function () {
+ var self = this;
+ this.states = [];
+ this._super.apply(this, arguments);
+ // hook on form view content changed: recompute the states, because it may be related to the current stage
+ this.getParent().on('view_content_has_changed', self, function () {
+ self.render_value();
+ });
+ },
prepare_dropdown_selection: function() {
var self = this;
var data = [];
- var selection = self.field.selection || [];
- _.map(selection, function(res) {
- var value = {
- 'name': res[0],
- 'tooltip': res[1],
- 'state_name': res[1],
- }
- if (res[0] == 'normal') { value['state_class'] = 'oe_kanban_status'; }
- else if (res[0] == 'done') { value['state_class'] = 'oe_kanban_status oe_kanban_status_green'; }
- else { value['state_class'] = 'oe_kanban_status oe_kanban_status_red'; }
- data.push(value);
+ var selection = this.field.selection || [];
+ var stage_id = _.isArray(this.view.datarecord.stage_id) ? this.view.datarecord.stage_id[0] : this.view.datarecord.stage_id;
+ var legend_field = this.options && this.options.states_legend_field || false;
+ var fields_to_read = _.map(
+ this.options && this.options.states_legend || {},
+ function (value, key, list) { return value; });
+ if (legend_field && fields_to_read && stage_id) {
+ var fetch_stage = new openerp.web.DataSet(
+ this,
+ self.view.fields[legend_field].field.relation).read_ids([stage_id],
+ fields_to_read);
+ }
+ else { var fetch_stage = $.Deferred().resolve(false); }
+ return $.when(fetch_stage).then(function (stage_data) {
+ _.map(selection, function(res) {
+ var value = {
+ 'name': res[0],
+ 'tooltip': res[1],
+ 'state_name': res[1],
+ }
+ if (stage_data && stage_data[0][self.options.states_legend[res[0]]]) {
+ value['state_name'] = stage_data[0][self.options.states_legend[res[0]]];
+ }
+ if (res[0] == 'normal') { value['state_class'] = 'oe_kanban_status'; }
+ else if (res[0] == 'done') { value['state_class'] = 'oe_kanban_status oe_kanban_status_green'; }
+ else { value['state_class'] = 'oe_kanban_status oe_kanban_status_red'; }
+ data.push(value);
+ });
+ return data;
});
- return data;
},
render_value: function() {
var self = this;
this.record_id = this.view.datarecord.id;
- this.states = this.prepare_dropdown_selection();;
- this.$el.html(QWeb.render("KanbanSelection", {'widget': self}));
- this.$el.find('li').on('click', this.set_kanban_selection.bind(this));
+ var dd_fetched = this.prepare_dropdown_selection();;
+ return $.when(dd_fetched).then(function (states) {
+ self.states = states;
+ self.$el.html(QWeb.render("KanbanSelection", {'widget': self}));
+ self.$el.find('li').on('click', self.set_kanban_selection.bind(self));
+ })
},
/* setting the value: in view mode, perform an asynchronous call and reload
the form view; in edit mode, use set_value to save the new value that will
var options = {
pickTime: true,
useSeconds: true,
- startDate: new moment({ y: 1900 }),
- endDate: new moment().add(200, "y"),
+ startDate: moment({ y: 1900 }),
+ endDate: moment().add(200, "y"),
calendarWeeks: true,
icons : {
time: 'fa fa-clock-o',
down: 'fa fa-chevron-down'
},
language : moment.locale(),
- format : instance.web.convert_to_moment_format(l10n.date_format +' '+ l10n.time_format),
+ format : instance.web.normalize_format(l10n.date_format +' '+ l10n.time_format),
};
this.$input = this.$el.find('input.oe_datepicker_master');
if (this.type_of_date === 'date') {
options['pickTime'] = false;
options['useSeconds'] = false;
- options['format'] = instance.web.convert_to_moment_format(l10n.date_format);
+ options['format'] = instance.web.normalize_format(l10n.date_format);
}
this.picker = this.$('.oe_datepicker_main').datetimepicker(options);
this.set_readonly(false);
//when opening datetimepicker the date and time by default should be the one from
//the input field if any or the current day otherwise
if (this.type_of_date === 'datetime') {
- value = new moment().second(0);
+ value = moment().second(0);
if (this.$input.val().length !== 0 && this.is_valid_()){
var value = this.$input.val();
}
render_value: function () {
var self = this;
this.$el.toggleClass("oe_readonly", this.get('effective_readonly'));
- this.$("input:checked").prop("checked", false);
if (this.get_value()) {
this.$("input").filter(function () {return this.value == self.get_value();}).prop("checked", true);
this.$(".oe_radio_readonly").text(this.get('value') ? this.get('value')[1] : "");
this.o2m.trigger_on_change();
},
is_valid: function () {
- var editor = this.editor;
- var form = editor.form;
- // If no edition is pending, the listview can not be invalid (?)
- if (!editor.record) {
- return true;
- }
- // If the form has not been modified, the view can only be valid
- // NB: is_dirty will also be set on defaults/onchanges/whatever?
- // oe_form_dirty seems to only be set on actual user actions
- if (!form.$el.is('.oe_form_dirty')) {
+ var self = this;
+ if (!this.fields_view || !this.editable()){
return true;
}
- this.o2m._dirty_flag = true;
-
- // Otherwise validate internal form
- return _(form.fields).chain()
- .invoke(function () {
- this._check_css_flags();
- return this.is_valid();
- })
- .all(_.identity)
- .value();
+ var r;
+ return _.every(this.records.records, function(record){
+ r = record;
+ _.each(self.editor.form.fields, function(field){
+ field._inhibit_on_change_flag = true;
+ field.set_value(r.attributes[field.name]);
+ field._inhibit_on_change_flag = false;
+ });
+ return _.every(self.editor.form.fields, function(field){
+ field.process_modifiers();
+ field._check_css_flags();
+ return field.is_valid();
+ });
+ });
},
do_add_record: function () {
if (this.editable()) {
this.model,
{
title: _t("Add: ") + this.m2m_field.string,
+ alternative_form_view: this.m2m_field.field.views ? this.m2m_field.field.views["form"] : undefined,
no_create: this.m2m_field.options.no_create,
},
new instance.web.CompoundDomain(this.m2m_field.build_domain(), ["!", ["id", "in", this.m2m_field.dataset.ids]]),
var pop = new instance.web.form.FormOpenPopup(this);
pop.show_element(this.dataset.model, id, this.m2m_field.build_context(), {
title: _t("Open: ") + this.m2m_field.string,
+ alternative_form_view: this.m2m_field.field.views ? this.m2m_field.field.views["form"] : undefined,
readonly: this.getParent().get("effective_readonly")
});
pop.on('write_completed', self, self.reload_content);
},
new_object: function() {
if (this.searchview) {
- this.searchview.hide();
+ this.searchview.do_hide();
}
if (this.view_list) {
this.view_list.do_hide();
* Options on attribute ; "blockui" {Boolean} block the UI or not
* during the file is uploading
*/
-instance.web.form.FieldMany2ManyBinaryMultiFiles = instance.web.form.AbstractField.extend({
+instance.web.form.FieldMany2ManyBinaryMultiFiles = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
template: "FieldBinaryFileUploader",
init: function(field_manager, node) {
this._super(field_manager, node);
this.fileupload_id = _.uniqueId('oe_fileupload_temp');
$(window).on(this.fileupload_id, _.bind(this.on_file_loaded, this));
},
- start: function() {
- this._super(this);
+ initialize_content: function() {
this.$el.on('change', 'input.oe_form_binary_file', this.on_file_change );
},
// WARNING: duplicated in 4 other M2M widgets
value: this.get("value") || 0,
};
if (! this.node.attrs.nolabel) {
- options.text = this.string
+ if(this.options.label_field && this.view.datarecord[this.options.label_field]) {
+ options.text = this.view.datarecord[this.options.label_field];
+ }
+ else {
+ options.text = this.string;
+ }
}
this.$el.html(QWeb.render("StatInfo", options));
},