[IMP] web_widget_one2many_product_picker: Auto apply changes without confirmation

pull/1858/head
Alexandre D. Díaz 2021-02-03 11:44:05 +01:00
parent b1a2804518
commit 015a50cbb3
4 changed files with 206 additions and 61 deletions

View File

@ -64,11 +64,24 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
}, },
/** /**
* Updates buttons depending on record status * Automatically create or accept changes
*
* @private
*/ */
_updateButtons: function () { auto: function () {
var state = this._getRecordState();
if (state === "new") {
this._add();
} else if (state === "dirty") {
this._change();
}
},
/**
* Know the real state of the record
* - record: Normal
* - new: Is a new record
* - dirty: Has changes
*/
_getRecordState: function () {
var record = this.model.get(this.handle); var record = this.model.get(this.handle);
var state = "record"; var state = "record";
if (this.model.isNew(record.id)) { if (this.model.isNew(record.id)) {
@ -89,12 +102,22 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
} }
} }
} }
return state;
},
/**
* Updates buttons depending on record status
*
* @private
*/
_updateButtons: function () {
this.$el.find( this.$el.find(
".oe_one2many_product_picker_form_buttons").remove(); ".oe_one2many_product_picker_form_buttons").remove();
this.$el.find(".o_form_view").append( this.$el.find(".o_form_view").append(
qweb.render( qweb.render(
"One2ManyProductPicker.QuickCreate.FormButtons", { "One2ManyProductPicker.QuickCreate.FormButtons", {
state: state, state: this._getRecordState(),
}) })
); );
}, },
@ -103,7 +126,9 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
* @private * @private
*/ */
_disableQuickCreate: function () { _disableQuickCreate: function () {
if (!this.$el) {
return;
}
// Ensures that the record won't be created twice // Ensures that the record won't be created twice
this._disabled = true; this._disabled = true;
this.$el.addClass("o_disabled"); this.$el.addClass("o_disabled");
@ -203,6 +228,10 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
* @returns {Deferred} * @returns {Deferred}
*/ */
_add: function () { _add: function () {
this.model.updateRecordContext(this.handle, {
has_changes_confirmed: true,
});
if (this._disabled) { if (this._disabled) {
// Don't do anything if we are already creating a record // Don't do anything if we are already creating a record
@ -223,38 +252,18 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
}); });
self.model.unsetDirty(self.handle); self.model.unsetDirty(self.handle);
self._updateButtons(); self._updateButtons();
self.trigger_up("restore_flip_card");
}); });
}, },
/** _remove: function () {
* @private this.trigger_up("restore_flip_card");
* @param {MouseEvent} ev
*/
_onClickAdd: function (ev) {
ev.stopPropagation();
this.model.updateRecordContext(this.handle, {
has_changes_confirmed: true,
});
this._add();
},
/**
* @private
* @param {MouseEvent} ev
*/
_onClickRemove: function (ev) {
ev.stopPropagation();
this.trigger_up("list_record_remove", { this.trigger_up("list_record_remove", {
id: this.renderer.state.id, id: this.renderer.state.id,
}); });
}, },
/** _change: function () {
* @private
* @param {MouseEvent} ev
*/
_onClickChange: function (ev) {
ev.stopPropagation();
this.model.updateRecordContext(this.handle, { this.model.updateRecordContext(this.handle, {
has_changes_confirmed: true, has_changes_confirmed: true,
}); });
@ -267,13 +276,8 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
this._updateButtons(); this._updateButtons();
}, },
/** _discard: function () {
* @private
* @param {MouseEvent} ev
*/
_onClickDiscard: function (ev) {
var self = this; var self = this;
ev.stopPropagation();
var record = this.model.get(this.handle); var record = this.model.get(this.handle);
this.model.discardChanges(this.handle, { this.model.discardChanges(this.handle, {
rollback: true, rollback: true,
@ -293,6 +297,42 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
}); });
} }
}, },
/**
* @private
* @param {MouseEvent} ev
*/
_onClickAdd: function (ev) {
ev.stopPropagation();
this._add();
},
/**
* @private
* @param {MouseEvent} ev
*/
_onClickRemove: function (ev) {
ev.stopPropagation();
this._remove();
},
/**
* @private
* @param {MouseEvent} ev
*/
_onClickChange: function (ev) {
ev.stopPropagation();
this._change();
},
/**
* @private
* @param {MouseEvent} ev
*/
_onClickDiscard: function (ev) {
ev.stopPropagation();
this._discard();
},
} }
); );

View File

@ -38,7 +38,10 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
this.subWidgets = {}; this.subWidgets = {};
this._clickFlipCardCount = 0; this._clickFlipCardCount = 0;
this._setState(state, options.searchRecord); this._setState(state, options.searchRecord);
this.widgets = []; this.widgets = {
front: [],
back: [],
};
}, },
/** /**
@ -71,6 +74,14 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
_.invoke(this.subWidgets, "on_detach_callback"); _.invoke(this.subWidgets, "on_detach_callback");
}, },
/**
* @override
*/
destroy: function () {
this.$card.off("")
this._super.apply(this, arguments);
},
/** /**
* @override * @override
*/ */
@ -94,6 +105,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
if (state) { if (state) {
this._setState(state); this._setState(state);
} }
// Avoid recreate active record
if (this.$card.hasClass("active")) {
this._processDynamicFields();
return $.when();
}
this.on_detach_callback(); this.on_detach_callback();
return this._render(); return this._render();
}, },
@ -238,10 +255,20 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
}); });
}, },
_detachAllWidgets: function () {
_.invoke(this.widgets.front, "on_detach_callback");
_.invoke(this.widgets.back, "on_detach_callback");
this.widgets = {
front: [],
back: [],
};
},
/** /**
* @override * @override
*/ */
_render: function () { _render: function () {
this._detachAllWidgets();
this.defs = []; this.defs = [];
this._replaceElement( this._replaceElement(
qweb.render( qweb.render(
@ -249,11 +276,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
this._getQWebContext() this._getQWebContext()
) )
); );
this.$el.data("renderer_widget_index", this.options.renderer_widget_index);
this.$card = this.$(".oe_flip_card"); this.$card = this.$(".oe_flip_card");
this.$front = this.$(".oe_flip_card_front"); this.$front = this.$(".oe_flip_card_front");
this.$back = this.$(".oe_flip_card_back"); this.$back = this.$(".oe_flip_card_back");
this._processWidgetFields(this.$front); this._processWidgetFields(this.$front);
this._processWidgets(this.$front); this._processWidgets(this.$front, 'front');
this._processDynamicFields(); this._processDynamicFields();
return $.when.apply(this, this.defs); return $.when.apply(this, this.defs);
}, },
@ -265,7 +293,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
* @private * @private
* @param {jQueryElement} $container * @param {jQueryElement} $container
*/ */
_processWidgetFields: function ($container) { _processWidgetFields: function ($container, widget_list) {
var self = this; var self = this;
$container.find("field").each(function () { $container.find("field").each(function () {
var $field = $(this); var $field = $(this);
@ -357,7 +385,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
* @private * @private
* @param {jQueryElement} $container * @param {jQueryElement} $container
*/ */
_processWidgets: function ($container) { _processWidgets: function ($container, widget_zone) {
var self = this; var self = this;
$container.find("widget").each(function () { $container.find("widget").each(function () {
var $field = $(this); var $field = $(this);
@ -375,7 +403,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
data: self.state && self.state.data, data: self.state && self.state.data,
}); });
self.widgets.push(widget); self.widgets[widget_zone].push(widget);
var def = widget var def = widget
._widgetRenderAndInsert(function () { ._widgetRenderAndInsert(function () {
@ -534,21 +562,28 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
} }
if (this.$card.hasClass("active")) { if (this.$card.hasClass("active")) {
this.$card.removeClass("active"); this.$card.removeClass("active");
this.$card.find('.oe_flip_card_front').removeClass("d-none"); this.$front.removeClass("d-none");
} else { } else {
var self = this; var self = this;
this.defs = []; this.defs = [];
if (!this.widgets.back.length) {
this._processWidgetFields(this.$back); this._processWidgetFields(this.$back);
this._processWidgets(this.$back); this._processWidgets(this.$back, 'back');
}
this._processDynamicFields(); this._processDynamicFields();
$.when(this.defs).then(function () { $.when(this.defs).then(function () {
var $actived_card = self.$el.parent().find(".active"); var $actived_card = self.$el.parent().find(".active");
$actived_card.removeClass("active"); $actived_card.removeClass("active");
$actived_card.find('.oe_flip_card_front').removeClass("d-none"); $actived_card.find('.oe_flip_card_front').removeClass("d-none");
self.$card.addClass("active"); self.$card.addClass("active");
setTimeout(function () { self.$card.on('transitionend', function () {
self.$('.oe_flip_card_front').addClass("d-none"); self.$front.addClass("d-none");
}, 200); self.$card.off('transitionend');
});
self.trigger_up("record_flip", {
widget_index: self.$el.data("renderer_widget_index"),
prev_widget_index: $actived_card.parent().data("renderer_widget_index"),
});
}); });
} }
}, },
@ -610,8 +645,23 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
* @private * @private
*/ */
_onRestoreFlipCard: function () { _onRestoreFlipCard: function () {
this.$(".oe_flip_card").removeClass("active"); var self = this;
this.$('.oe_flip_card_front').removeClass("d-none"); this.$card.removeClass("active");
this.$front.removeClass("d-none");
if (this.$card.hasClass('oe_flip_card_maximized')) {
this.$card.removeClass('oe_flip_card_maximized');
this.$card.on('transitionend', function () {
self.$card.css({
position: "",
top: "",
left: "",
width: "",
height: "",
zIndex: "",
});
self.$card.off('transitionend');
});
}
}, },
/** /**

View File

@ -9,6 +9,8 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
var BasicRenderer = require("web.BasicRenderer"); var BasicRenderer = require("web.BasicRenderer");
var One2ManyProductPickerRecord = require( var One2ManyProductPickerRecord = require(
"web_widget_one2many_product_picker.One2ManyProductPickerRecord"); "web_widget_one2many_product_picker.One2ManyProductPickerRecord");
var ProductPickerQuickCreateForm = require(
"web_widget_one2many_product_picker.ProductPickerQuickCreateForm");
var qweb = core.qweb; var qweb = core.qweb;
@ -19,6 +21,9 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
events: { events: {
'click #productPickerLoadMore': '_onClickLoadMore', 'click #productPickerLoadMore': '_onClickLoadMore',
}, },
custom_events: {
'record_flip': '_onRecordFlip',
},
DELAY_GET_RECORDS: 150, DELAY_GET_RECORDS: 150,
MIN_PERC_GET_RECORDS: 0.9, MIN_PERC_GET_RECORDS: 0.9,
@ -62,8 +67,9 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
* @param {Object} widget * @param {Object} widget
*/ */
removeWidget: function (widget) { removeWidget: function (widget) {
this.widgets.splice(this.widgets.indexOf(widget), 1); var index = this.widgets.indexOf(widget);
widget.destroy(); widget.destroy();
delete this.widgets[index];
}, },
/** /**
@ -128,7 +134,6 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
} }
} }
} }
this.widgets = _.compact(this.widgets);
if (this.search_group.name === "main_lines") { if (this.search_group.name === "main_lines") {
_.invoke(to_destroy, "destroy"); _.invoke(to_destroy, "destroy");
@ -145,6 +150,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
for (var eb = this.widgets.length-1; eb>=0; --eb) { for (var eb = this.widgets.length-1; eb>=0; --eb) {
var widget = this.widgets[eb]; var widget = this.widgets[eb];
if ( if (
widget &&
widget.state.data[this.options.field_map.product].data.id === widget_product_id widget.state.data[this.options.field_map.product].data.id === widget_product_id
) { ) {
found = true; found = true;
@ -230,7 +236,8 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
// Remove "pure virtual" records that have the same product that the new record // Remove "pure virtual" records that have the same product that the new record
if ( if (
widget.is_virtual && widget.is_virtual &&
widget.state.data[this.options.field_map.product].data.id === state.data[this.options.field_map.product].data.id widget.state.data[this.options.field_map.product].data.id === state.data[this.options.field_map.product].data.id &&
widget.state.data[this.options.compa].data.id === state.data[this.options.field_map.product].data.id
) { ) {
to_destroy.push(widget); to_destroy.push(widget);
delete this.widgets[e]; delete this.widgets[e];
@ -243,7 +250,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
defs.push(this.appendSearchRecords([new_search_record], false, true, search_record_index)[0]); defs.push(this.appendSearchRecords([new_search_record], false, true, search_record_index)[0]);
} }
} }
this.widgets = _.compact(this.widgets);
_.invoke(to_destroy, "destroy"); _.invoke(to_destroy, "destroy");
return $.when(defs); return $.when(defs);
}, },
@ -360,10 +367,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
no_process_records?search_records:this._processSearchRecords(search_records); no_process_records?search_records:this._processSearchRecords(search_records);
_.each(processed_records, function (search_record) { _.each(processed_records, function (search_record) {
var state_data = self._getRecordDataById(search_record.__id); var state_data = self._getRecordDataById(search_record.__id);
var widget_options = self._getRecordOptions(search_record);
widget_options.renderer_widget_index = self.widgets.length;
var ProductPickerRecord = new One2ManyProductPickerRecord( var ProductPickerRecord = new One2ManyProductPickerRecord(
self, self,
state_data, state_data,
self._getRecordOptions(search_record) widget_options
); );
self.widgets.push(ProductPickerRecord); self.widgets.push(ProductPickerRecord);
@ -380,12 +389,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
// the search data. Using search data instead of waiting for // the search data. Using search data instead of waiting for
// simulated state gives a low FCP time. // simulated state gives a low FCP time.
var def = ProductPickerRecord.appendTo(self.$recordsContainer) var def = ProductPickerRecord.appendTo(self.$recordsContainer)
.then(function () { .then(function (widget, widget_position) {
if (typeof position !== "undefined") { if (typeof widget_position !== "undefined") {
var $elm = self.$el.find("> div > div:nth("+position+")"); var $elm = this.$el.find("> div > div:nth("+widget_position+")");
ProductPickerRecord.$el.insertAfter($elm); widget.$el.insertAfter($elm);
} }
}); }.bind(self, ProductPickerRecord, position));
if (def.state() === "pending") { if (def.state() === "pending") {
self.defs.push(def); self.defs.push(def);
} }
@ -441,6 +450,53 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
this._loadMoreWorking = true; this._loadMoreWorking = true;
}, },
/**
* Do card flip
*
* @param {Integer} index
*/
doWidgetFlip: function (index) {
var widget = this.widgets[index];
var $actived_card = this.$el.find(".active");
if (widget.$card.hasClass("active")) {
widget.$card.removeClass("active");
widget.$card.find('.oe_flip_card_front').removeClass("d-none");
} else {
var self = widget;
widget.defs = [];
widget._processWidgetFields(widget.$back);
widget._processWidgets(widget.$back);
widget._processDynamicFields();
$.when(widget.defs).then(function () {
$actived_card.removeClass("active");
$actived_card.find('.oe_flip_card_front').removeClass("d-none");
self.$card.addClass("active");
setTimeout(function () {
self.$('.oe_flip_card_front').addClass("d-none");
}, 200);
});
}
},
/**
* Handle card flip.
* Used to create/update the record
*
* @param {CustomEvent} evt
*/
_onRecordFlip: function (evt) {
var prev_widget_index = evt.data.prev_widget_index;
if (typeof prev_widget_index !== "undefined") {
// Only check 'back' widgets so there is where the form was created
for (var index in this.widgets[prev_widget_index].widgets.back) {
var widget = this.widgets[prev_widget_index].widgets.back[index];
if (widget instanceof ProductPickerQuickCreateForm) {
widget.controller.auto();
}
}
}
}
}); });
return One2ManyProductPickerRenderer; return One2ManyProductPickerRenderer;

View File

@ -1,7 +1,6 @@
$one2many-product-picker-max-height: 500px;
$one2many-product-picker-card-min-height: 150px; $one2many-product-picker-card-min-height: 150px;
$one2many-product-picker-card-max-height: 150px; $one2many-product-picker-card-max-height: 150px;
$one2many-product-picker-transition-3d-time: 0.3s; $one2many-product-picker-transition-3d-time: 0.15s;
$one2many-product-picker-card-form-padding: 0em; $one2many-product-picker-card-form-padding: 0em;
$one2many-product-picker-quick-modif-price-max-width: 400px; $one2many-product-picker-quick-modif-price-max-width: 400px;
$one2many-product-picker-zoom-scale: 1.4; $one2many-product-picker-zoom-scale: 1.4;