forked from Techsystech/web
[IMP] web_widget_one2many_product_picker-response: User experience
parent
4dbb75abc4
commit
6a10e3703f
|
@ -255,6 +255,7 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
|
|||
viewType: "form",
|
||||
}).then(function () {
|
||||
var record = self.model.get(self.handle);
|
||||
self.model.updateRecordContext(self.handle, {saving: true});
|
||||
self.trigger_up("restore_flip_card", {
|
||||
success_callback: function () {
|
||||
self.trigger_up("create_quick_record", {
|
||||
|
|
|
@ -108,11 +108,13 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
if (state) {
|
||||
this._setState(state);
|
||||
}
|
||||
this.$card.removeClass("blocked");
|
||||
// Avoid recreate active record
|
||||
if (this.$card.hasClass("active")) {
|
||||
this._processDynamicFields();
|
||||
return $.when();
|
||||
if (this.$card && this.$card.length) {
|
||||
this.$card.removeClass("blocked");
|
||||
// Avoid recreate active record
|
||||
if (this.$card.hasClass("active")) {
|
||||
this._processDynamicFields();
|
||||
return $.when();
|
||||
}
|
||||
}
|
||||
|
||||
this.on_detach_callback();
|
||||
|
@ -187,6 +189,17 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
}
|
||||
var model = this.options.basicFieldParams.model;
|
||||
this.is_virtual = this.state && model.isPureVirtual(this.state.id) || false;
|
||||
|
||||
// Check if has cached qty
|
||||
if (this.state && this.state.id) {
|
||||
const record = model.get(this.state.id);
|
||||
const lazy_qty = record && record.context.lazy_qty || 0;
|
||||
if (lazy_qty) {
|
||||
model.updateRecordContext(this.state.id, {lazy_qty: 0});
|
||||
// Record already has 1
|
||||
this._incProductQty(lazy_qty - 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -214,6 +227,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
modified: record && record.context.product_picker_modified,
|
||||
active_model: '',
|
||||
auto_save: this.options.autoSave,
|
||||
is_saving: record && record.context.saving,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -429,6 +443,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
});
|
||||
},
|
||||
|
||||
_updateLazyQty: function () {
|
||||
var model = this.options.basicFieldParams.model;
|
||||
var record = model.get(this.state.id);
|
||||
this.$el.find(".lazy_product_qty").text(record.context.lazy_qty);
|
||||
},
|
||||
|
||||
/**
|
||||
* This is a special handle for display the non-fields.
|
||||
* Similar 't-esc' behaviour.
|
||||
|
@ -516,6 +536,8 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
_saveRecord: function () {
|
||||
var self = this;
|
||||
var model = this.options.basicFieldParams.model;
|
||||
model.updateRecordContext(this.state.id, {saving: true});
|
||||
this.recreate();
|
||||
var record = model.get(this.state.id);
|
||||
return model.save(record.id, {
|
||||
stayInEdit: true,
|
||||
|
@ -559,6 +581,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
var model = this.options.basicFieldParams.model;
|
||||
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
|
||||
var record = model.get(this.state.id);
|
||||
|
||||
// Because we don't hide the 'add' button when the product is added form back form
|
||||
// we check if the record is in "saving" mode to prevent duplicate it.
|
||||
if (record.context.saving) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
|
||||
if (changes[this.options.fieldMap.product_uom_qty] === 0) {
|
||||
changes[this.options.fieldMap.product_uom_qty] = 1;
|
||||
|
@ -583,16 +611,23 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
var model = this.options.basicFieldParams.model;
|
||||
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
|
||||
var record = model.get(this.state.id);
|
||||
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
|
||||
changes[this.options.fieldMap.product_uom_qty] += amount;
|
||||
|
||||
return model.notifyChanges(
|
||||
record.id,
|
||||
changes
|
||||
).then(function () {
|
||||
self._processDynamicFields();
|
||||
self._lazyUpdateRecord();
|
||||
});
|
||||
if (this.options.autoSave && !this.state.data.id) {
|
||||
let lazy_qty = record.context.lazy_qty || 1;
|
||||
lazy_qty += amount;
|
||||
model.updateRecordContext(this.state.id, {lazy_qty: lazy_qty});
|
||||
self._updateLazyQty();
|
||||
} else {
|
||||
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
|
||||
changes[this.options.fieldMap.product_uom_qty] += amount;
|
||||
return model.notifyChanges(
|
||||
record.id,
|
||||
changes
|
||||
).then(function () {
|
||||
self._processDynamicFields();
|
||||
self._lazyUpdateRecord();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -603,11 +638,6 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
var $currentTarget = $(currentTarget);
|
||||
var $img = $currentTarget.find(".oe_flip_card_front img");
|
||||
$target.addClass('o_catch_attention');
|
||||
$img.addClass('oe_product_picker_catch_attention');
|
||||
$img.on('animationend', function () {
|
||||
$img.removeClass('oe_product_picker_catch_attention');
|
||||
$img.off('animationend');
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -645,7 +675,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
*/
|
||||
_onClickFlipCard: function (evt) {
|
||||
// Avoid clicks on form elements
|
||||
if (['INPUT', 'BUTTON', 'A'].indexOf(evt.target.tagName) !== -1 || this.$card.hasClass('blocked')) {
|
||||
if (['INPUT', 'BUTTON', 'A'].indexOf(evt.target.tagName) !== -1) {
|
||||
return;
|
||||
}
|
||||
var $target = $(evt.target);
|
||||
|
@ -672,6 +702,11 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.$card.hasClass('blocked')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._clickFlipCardDelayed) {
|
||||
this._clickFlipCardDelayed = setTimeout(
|
||||
this._onClickDelayedFlipCard.bind(this, evt),
|
||||
|
|
|
@ -260,9 +260,14 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRenderer",
|
|||
widget.recordSearch.id === state.data[this.options.field_map.product].data.id
|
||||
) {
|
||||
|
||||
// Is a new record
|
||||
// Is a new record (a replace for pure virtual)
|
||||
search_record_index = widget.$el.index();
|
||||
search_record = widget.recordSearch;
|
||||
var model = this.getParent().getBasicFieldParams().model;
|
||||
var record = model.get(widget.state.id);
|
||||
model.updateRecordContext(state.id, {
|
||||
lazy_qty: record.context.lazy_qty || 0,
|
||||
});
|
||||
}
|
||||
|
||||
// Remove "pure virtual" records that have the same product that the new record
|
||||
|
|
|
@ -604,6 +604,9 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
|
|||
}
|
||||
});
|
||||
});
|
||||
if (evt.data.callback) {
|
||||
evt.data.callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// This is used to know when need use 'yellow' color
|
||||
|
@ -619,6 +622,45 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
|
|||
}
|
||||
},
|
||||
|
||||
_doUpdateQuickRecord: function (id, data, callback) {
|
||||
if (this.options.auto_save) {
|
||||
var self = this;
|
||||
// Dont trigger state update
|
||||
this._setValue(
|
||||
{operation: "UPDATE", id: id, data: data},
|
||||
{notifyChange: false}
|
||||
).then(function () {
|
||||
self.parent_controller.saveRecord(undefined, {stayInEdit: true}).then(function () {
|
||||
// Workaround to get updated values
|
||||
self.parent_controller.model.reload(self.value.id).then(function (result) {
|
||||
var new_data = self.parent_controller.model.get(result);
|
||||
self.value.data = new_data.data;
|
||||
self.renderer.updateState(self.value, {force: true});
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
});
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// This is used to know when need use 'yellow' color
|
||||
this.parent_controller.model.updateRecordContext(id, {
|
||||
product_picker_modified: true,
|
||||
});
|
||||
// This will trigger an "state" update
|
||||
this._setValue(
|
||||
{operation: "UPDATE", id: id, data: data},
|
||||
).then(function () {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Runs the x2many (1,id,values) command.
|
||||
*
|
||||
|
@ -627,44 +669,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
|
|||
*/
|
||||
_onUpdateQuickRecord: function (evt) {
|
||||
evt.stopPropagation();
|
||||
var self = this;
|
||||
|
||||
if (this.options.auto_save) {
|
||||
// Dont trigger state update
|
||||
this._setValue(
|
||||
{operation: "UPDATE", id: evt.data.id, data: evt.data.data},
|
||||
{notifyChange: false}
|
||||
).then(function () {
|
||||
if (self.options.auto_save) {
|
||||
self.parent_controller.saveRecord(undefined, {stayInEdit: true}).then(function () {
|
||||
// Workaround to get updated values
|
||||
self.parent_controller.model.reload(self.value.id).then(function (result) {
|
||||
var new_data = self.parent_controller.model.get(result);
|
||||
self.value.data = new_data.data;
|
||||
self.renderer.updateState(self.value, {force: true});
|
||||
if (evt.data.callback) {
|
||||
evt.data.callback();
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (evt.data.callback) {
|
||||
evt.data.callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// This is used to know when need use 'yellow' color
|
||||
this.parent_controller.model.updateRecordContext(evt.data.id, {
|
||||
product_picker_modified: true,
|
||||
});
|
||||
// This will trigger an "state" update
|
||||
this._setValue(
|
||||
{operation: "UPDATE", id: evt.data.id, data: evt.data.data},
|
||||
).then(function () {
|
||||
if (evt.data.callback) {
|
||||
evt.data.callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
this._doUpdateQuickRecord(evt.data.id, evt.data.data, evt.data.callback);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -61,10 +61,6 @@
|
|||
transition: top $one2many-product-picker-transition-3d-time, left $one2many-product-picker-transition-3d-time, width $one2many-product-picker-transition-3d-time, height $one2many-product-picker-transition-3d-time;
|
||||
height: $one2many-product-picker-card-min-height;
|
||||
|
||||
&.blocked {
|
||||
filter: blur(2px);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
filter: grayscale(100%);
|
||||
opacity: 0.5;
|
||||
|
@ -239,20 +235,3 @@
|
|||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.oe_product_picker_catch_attention {
|
||||
position: relative;
|
||||
animation: productPickerCatchAttention 200ms normal forwards;
|
||||
}
|
||||
|
||||
@keyframes productPickerCatchAttention {
|
||||
0% {
|
||||
transform: scale(1.0);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.5);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,15 +70,20 @@
|
|||
|
||||
<t t-name="One2ManyProductPicker.FlipCard">
|
||||
<div class="oe_flip_container p-1 col-12 col-sm-8 col-md-6 col-lg-4 col-xl-3 col-xxl-2">
|
||||
<div t-attf-class="oe_flip_card {{!state && 'disabled' || (auto_save && !is_virtual && !state.data.id && 'blocked') || ''}}">
|
||||
<div t-attf-class="oe_flip_card {{!state && 'disabled' || (auto_save && (!is_virtual || is_saving) && !state.data.id && 'blocked') || ''}}">
|
||||
<div class="oe_flip_card_inner text-center">
|
||||
<div t-attf-class="oe_flip_card_front p-0 {{(modified && 'border-warning') || (state && !is_virtual && 'border-success') || ''}}">
|
||||
<div t-attf-class="oe_flip_card_front p-0 {{((modified || is_saving) && 'border-warning') || (state && !is_virtual && 'border-success') || ''}}">
|
||||
<t t-if="state">
|
||||
<t t-if="!is_virtual">
|
||||
<div class="safezone position-absolute m-0 pb-2 pr-2 text-left">
|
||||
<span t-att-data-field="field_map.product_uom_qty" t-attf-data-esc="str({{field_map.product_uom_qty}}) + ' x ' + {{field_map.product_uom}}.data.display_name" t-attf-class="badge {{modified && 'badge-warning' || 'badge-success'}} font-weight-bold rounded-0 mt-0 px-2 py-3 product_qty" />
|
||||
</div>
|
||||
</t>
|
||||
<t t-elif="is_saving">
|
||||
<div class="safezone position-absolute m-0 pb-2 pr-2 text-left">
|
||||
<span class="badge record_saving badge-warning font-weight-bold rounded-0 mt-0 px-2 py-3 product_qty"><span class="lazy_product_qty">1</span> x <t t-esc="state.data[field_map.product_uom].data.display_name"/></span>
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div class="safezone position-absolute m-0 pb-2 pr-2 text-left">
|
||||
<span class="badge badge-primary font-weight-bold rounded-0 mt-0 px-2 py-3 add_product"><i class="fa fa-plus"></i> 1 <t t-esc="state.data[field_map.product_uom].data.display_name"/></span>
|
||||
|
|
Loading…
Reference in New Issue