[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
*
* @private
* Automatically create or accept changes
*/
_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 state = "record";
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(
".oe_one2many_product_picker_form_buttons").remove();
this.$el.find(".o_form_view").append(
qweb.render(
"One2ManyProductPicker.QuickCreate.FormButtons", {
state: state,
state: this._getRecordState(),
})
);
},
@ -103,7 +126,9 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
* @private
*/
_disableQuickCreate: function () {
if (!this.$el) {
return;
}
// Ensures that the record won't be created twice
this._disabled = true;
this.$el.addClass("o_disabled");
@ -203,6 +228,10 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
* @returns {Deferred}
*/
_add: function () {
this.model.updateRecordContext(this.handle, {
has_changes_confirmed: true,
});
if (this._disabled) {
// 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._updateButtons();
self.trigger_up("restore_flip_card");
});
},
/**
* @private
* @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();
_remove: function () {
this.trigger_up("restore_flip_card");
this.trigger_up("list_record_remove", {
id: this.renderer.state.id,
});
},
/**
* @private
* @param {MouseEvent} ev
*/
_onClickChange: function (ev) {
ev.stopPropagation();
_change: function () {
this.model.updateRecordContext(this.handle, {
has_changes_confirmed: true,
});
@ -267,13 +276,8 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
this._updateButtons();
},
/**
* @private
* @param {MouseEvent} ev
*/
_onClickDiscard: function (ev) {
_discard: function () {
var self = this;
ev.stopPropagation();
var record = this.model.get(this.handle);
this.model.discardChanges(this.handle, {
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._clickFlipCardCount = 0;
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");
},
/**
* @override
*/
destroy: function () {
this.$card.off("")
this._super.apply(this, arguments);
},
/**
* @override
*/
@ -94,6 +105,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
if (state) {
this._setState(state);
}
// Avoid recreate active record
if (this.$card.hasClass("active")) {
this._processDynamicFields();
return $.when();
}
this.on_detach_callback();
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
*/
_render: function () {
this._detachAllWidgets();
this.defs = [];
this._replaceElement(
qweb.render(
@ -249,11 +276,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
this._getQWebContext()
)
);
this.$el.data("renderer_widget_index", this.options.renderer_widget_index);
this.$card = this.$(".oe_flip_card");
this.$front = this.$(".oe_flip_card_front");
this.$back = this.$(".oe_flip_card_back");
this._processWidgetFields(this.$front);
this._processWidgets(this.$front);
this._processWidgets(this.$front, 'front');
this._processDynamicFields();
return $.when.apply(this, this.defs);
},
@ -265,7 +293,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
* @private
* @param {jQueryElement} $container
*/
_processWidgetFields: function ($container) {
_processWidgetFields: function ($container, widget_list) {
var self = this;
$container.find("field").each(function () {
var $field = $(this);
@ -357,7 +385,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
* @private
* @param {jQueryElement} $container
*/
_processWidgets: function ($container) {
_processWidgets: function ($container, widget_zone) {
var self = this;
$container.find("widget").each(function () {
var $field = $(this);
@ -375,7 +403,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
data: self.state && self.state.data,
});
self.widgets.push(widget);
self.widgets[widget_zone].push(widget);
var def = widget
._widgetRenderAndInsert(function () {
@ -534,21 +562,28 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
}
if (this.$card.hasClass("active")) {
this.$card.removeClass("active");
this.$card.find('.oe_flip_card_front').removeClass("d-none");
this.$front.removeClass("d-none");
} else {
var self = this;
this.defs = [];
if (!this.widgets.back.length) {
this._processWidgetFields(this.$back);
this._processWidgets(this.$back);
this._processWidgets(this.$back, 'back');
}
this._processDynamicFields();
$.when(this.defs).then(function () {
var $actived_card = self.$el.parent().find(".active");
$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);
self.$card.on('transitionend', function () {
self.$front.addClass("d-none");
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
*/
_onRestoreFlipCard: function () {
this.$(".oe_flip_card").removeClass("active");
this.$('.oe_flip_card_front').removeClass("d-none");
var self = this;
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 One2ManyProductPickerRecord = require(
"web_widget_one2many_product_picker.One2ManyProductPickerRecord");
var ProductPickerQuickCreateForm = require(
"web_widget_one2many_product_picker.ProductPickerQuickCreateForm");
var qweb = core.qweb;
@ -19,6 +21,9 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
events: {
'click #productPickerLoadMore': '_onClickLoadMore',
},
custom_events: {
'record_flip': '_onRecordFlip',
},
DELAY_GET_RECORDS: 150,
MIN_PERC_GET_RECORDS: 0.9,
@ -62,8 +67,9 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
* @param {Object} widget
*/
removeWidget: function (widget) {
this.widgets.splice(this.widgets.indexOf(widget), 1);
var index = this.widgets.indexOf(widget);
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") {
_.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) {
var widget = this.widgets[eb];
if (
widget &&
widget.state.data[this.options.field_map.product].data.id === widget_product_id
) {
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
if (
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);
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]);
}
}
this.widgets = _.compact(this.widgets);
_.invoke(to_destroy, "destroy");
return $.when(defs);
},
@ -360,10 +367,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
no_process_records?search_records:this._processSearchRecords(search_records);
_.each(processed_records, function (search_record) {
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(
self,
state_data,
self._getRecordOptions(search_record)
widget_options
);
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
// simulated state gives a low FCP time.
var def = ProductPickerRecord.appendTo(self.$recordsContainer)
.then(function () {
if (typeof position !== "undefined") {
var $elm = self.$el.find("> div > div:nth("+position+")");
ProductPickerRecord.$el.insertAfter($elm);
.then(function (widget, widget_position) {
if (typeof widget_position !== "undefined") {
var $elm = this.$el.find("> div > div:nth("+widget_position+")");
widget.$el.insertAfter($elm);
}
});
}.bind(self, ProductPickerRecord, position));
if (def.state() === "pending") {
self.defs.push(def);
}
@ -441,6 +450,53 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
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;

View File

@ -1,7 +1,6 @@
$one2many-product-picker-max-height: 500px;
$one2many-product-picker-card-min-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-quick-modif-price-max-width: 400px;
$one2many-product-picker-zoom-scale: 1.4;