mirror of https://github.com/OCA/web.git
commit
7af421ddf1
|
@ -255,6 +255,7 @@ odoo.define("web_widget_one2many_product_picker.ProductPickerQuickCreateFormView
|
||||||
viewType: "form",
|
viewType: "form",
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
var record = self.model.get(self.handle);
|
var record = self.model.get(self.handle);
|
||||||
|
self.model.updateRecordContext(self.handle, {saving: true});
|
||||||
self.trigger_up("restore_flip_card", {
|
self.trigger_up("restore_flip_card", {
|
||||||
success_callback: function () {
|
success_callback: function () {
|
||||||
self.trigger_up("create_quick_record", {
|
self.trigger_up("create_quick_record", {
|
||||||
|
|
|
@ -108,12 +108,14 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
||||||
if (state) {
|
if (state) {
|
||||||
this._setState(state);
|
this._setState(state);
|
||||||
}
|
}
|
||||||
|
if (this.$card && this.$card.length) {
|
||||||
this.$card.removeClass("blocked");
|
this.$card.removeClass("blocked");
|
||||||
// Avoid recreate active record
|
// Avoid recreate active record
|
||||||
if (this.$card.hasClass("active")) {
|
if (this.$card.hasClass("active")) {
|
||||||
this._processDynamicFields();
|
this._processDynamicFields();
|
||||||
return $.when();
|
return $.when();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.on_detach_callback();
|
this.on_detach_callback();
|
||||||
return this._render();
|
return this._render();
|
||||||
|
@ -187,6 +189,17 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
||||||
}
|
}
|
||||||
var model = this.options.basicFieldParams.model;
|
var model = this.options.basicFieldParams.model;
|
||||||
this.is_virtual = this.state && model.isPureVirtual(this.state.id) || false;
|
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,
|
modified: record && record.context.product_picker_modified,
|
||||||
active_model: '',
|
active_model: '',
|
||||||
auto_save: this.options.autoSave,
|
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.
|
* This is a special handle for display the non-fields.
|
||||||
* Similar 't-esc' behaviour.
|
* Similar 't-esc' behaviour.
|
||||||
|
@ -516,6 +536,8 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
||||||
_saveRecord: function () {
|
_saveRecord: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
var model = this.options.basicFieldParams.model;
|
var model = this.options.basicFieldParams.model;
|
||||||
|
model.updateRecordContext(this.state.id, {saving: true});
|
||||||
|
this.recreate();
|
||||||
var record = model.get(this.state.id);
|
var record = model.get(this.state.id);
|
||||||
return model.save(record.id, {
|
return model.save(record.id, {
|
||||||
stayInEdit: true,
|
stayInEdit: true,
|
||||||
|
@ -559,6 +581,12 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
||||||
var model = this.options.basicFieldParams.model;
|
var model = this.options.basicFieldParams.model;
|
||||||
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
|
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
|
||||||
var record = model.get(this.state.id);
|
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);
|
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
|
||||||
if (changes[this.options.fieldMap.product_uom_qty] === 0) {
|
if (changes[this.options.fieldMap.product_uom_qty] === 0) {
|
||||||
changes[this.options.fieldMap.product_uom_qty] = 1;
|
changes[this.options.fieldMap.product_uom_qty] = 1;
|
||||||
|
@ -583,9 +611,15 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
||||||
var model = this.options.basicFieldParams.model;
|
var model = this.options.basicFieldParams.model;
|
||||||
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
|
model.updateRecordContext(this.state.id, {ignore_warning: this.options.ignoreWarning});
|
||||||
var record = model.get(this.state.id);
|
var record = model.get(this.state.id);
|
||||||
|
|
||||||
|
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);
|
var changes = _.pick(record.data, this.options.fieldMap.product_uom_qty);
|
||||||
changes[this.options.fieldMap.product_uom_qty] += amount;
|
changes[this.options.fieldMap.product_uom_qty] += amount;
|
||||||
|
|
||||||
return model.notifyChanges(
|
return model.notifyChanges(
|
||||||
record.id,
|
record.id,
|
||||||
changes
|
changes
|
||||||
|
@ -593,6 +627,7 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
||||||
self._processDynamicFields();
|
self._processDynamicFields();
|
||||||
self._lazyUpdateRecord();
|
self._lazyUpdateRecord();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -603,11 +638,6 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
||||||
var $currentTarget = $(currentTarget);
|
var $currentTarget = $(currentTarget);
|
||||||
var $img = $currentTarget.find(".oe_flip_card_front img");
|
var $img = $currentTarget.find(".oe_flip_card_front img");
|
||||||
$target.addClass('o_catch_attention');
|
$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) {
|
_onClickFlipCard: function (evt) {
|
||||||
// Avoid clicks on form elements
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
var $target = $(evt.target);
|
var $target = $(evt.target);
|
||||||
|
@ -672,6 +702,11 @@ odoo.define("web_widget_one2many_product_picker.One2ManyProductPickerRecord", fu
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.$card.hasClass('blocked')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this._clickFlipCardDelayed) {
|
if (!this._clickFlipCardDelayed) {
|
||||||
this._clickFlipCardDelayed = setTimeout(
|
this._clickFlipCardDelayed = setTimeout(
|
||||||
this._onClickDelayedFlipCard.bind(this, evt),
|
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
|
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_index = widget.$el.index();
|
||||||
search_record = widget.recordSearch;
|
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
|
// 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 {
|
} else {
|
||||||
// This is used to know when need use 'yellow' color
|
// 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.
|
* Runs the x2many (1,id,values) command.
|
||||||
*
|
*
|
||||||
|
@ -627,44 +669,7 @@ odoo.define("web_widget_one2many_product_picker.FieldOne2ManyProductPicker", fun
|
||||||
*/
|
*/
|
||||||
_onUpdateQuickRecord: function (evt) {
|
_onUpdateQuickRecord: function (evt) {
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
var self = this;
|
this._doUpdateQuickRecord(evt.data.id, evt.data.data, evt.data.callback);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
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;
|
height: $one2many-product-picker-card-min-height;
|
||||||
|
|
||||||
&.blocked {
|
|
||||||
filter: blur(2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
filter: grayscale(100%);
|
filter: grayscale(100%);
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
@ -239,20 +235,3 @@
|
||||||
text-align: center;
|
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">
|
<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 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 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="state">
|
||||||
<t t-if="!is_virtual">
|
<t t-if="!is_virtual">
|
||||||
<div class="safezone position-absolute m-0 pb-2 pr-2 text-left">
|
<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" />
|
<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>
|
</div>
|
||||||
</t>
|
</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="">
|
<t t-else="">
|
||||||
<div class="safezone position-absolute m-0 pb-2 pr-2 text-left">
|
<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>
|
<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