[IMP] web_editor: allow to enable option widgets by enabling another

With this commit, we can now say "on preview/selection of a widget,
also preview/selection these other widgets". For this, add a
`data-trigger` with comma-separated widget names.

A `data-trigger-value` can also be used to indicate the values these
other widgets should have during preview/selection... but this currently
only works for colorpicker widgets thanks to a big big hack that should
be improved later.

Part of https://github.com/odoo/odoo/pull/42986

closes odoo/odoo#42986

Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
qsm-odoo
2020-01-09 13:09:50 +00:00
parent 03ee121d6a
commit e590609ebb
@@ -280,12 +280,18 @@ const UserValueWidget = Widget.extend({
this._methodsParams = _.extend({}, extraParams);
this._methodsParams.optionsPossibleValues = {};
this._dependencies = [];
this._triggerWidgetsNames = [];
this._triggerWidgetsValues = [];
for (const key in this.el.dataset) {
const dataValue = this.el.dataset[key].trim();
if (key === 'dependencies') {
this._dependencies.push(...dataValue.split(/\s*,\s*/g));
} else if (key === 'trigger') {
this._triggerWidgetsNames.push(...dataValue.split(/\s*,\s*/g));
} else if (key === 'triggerValue') {
this._triggerWidgetsValues.push(...dataValue.split(/\s*,\s*/g));
} else if (validMethodNames.includes(key)) {
this._methodsNames.push(key);
this._methodsParams.optionsPossibleValues[key] = dataValue.split(/\s*\|\s*/g);
@@ -318,8 +324,9 @@ const UserValueWidget = Widget.extend({
},
/**
* @param {boolean} [previewMode=false]
* @param {boolean} [isSimulatedEvent=false]
*/
notifyValueChange: function (previewMode) {
notifyValueChange: function (previewMode, isSimulatedEvent) {
// If the widget has no associated method, it should not notify user
// value changes
if (!this._methodsNames.length) {
@@ -339,6 +346,7 @@ const UserValueWidget = Widget.extend({
const data = {
previewMode: previewMode || false,
isSimulatedEvent: !!isSimulatedEvent,
};
// TODO improve this. The preview state has to be updated only when the
// actual option _select is gonna be called... but this is delayed by a
@@ -465,6 +473,16 @@ const UserValueWidget = Widget.extend({
*/
_onUserValueNotification: function (ev) {
ev.data.widget = this;
if (!ev.data.triggerWidgetsNames) {
ev.data.triggerWidgetsNames = [];
}
ev.data.triggerWidgetsNames.push(...this._triggerWidgetsNames);
if (!ev.data.triggerWidgetsValues) {
ev.data.triggerWidgetsValues = [];
}
ev.data.triggerWidgetsValues.push(...this._triggerWidgetsValues);
},
/**
* Should be called when an user event on the widget indicates a value
@@ -2001,15 +2019,17 @@ const SnippetOptionWidget = Widget.extend({
* @param {Event} ev
*/
_onUserValueUpdate: function (ev) {
ev.stopPropagation();
const widget = ev.data.widget;
const previewMode = ev.data.previewMode;
ev.stopPropagation();
// Ask a mutexed snippet update according to the widget value change
const shouldRecordUndo = (!previewMode && !ev.data.isSimulatedEvent);
this.trigger_up('snippet_edition_request', {exec: async () => {
if (ev.data.prepare) {
ev.data.prepare();
}
const widget = ev.data.widget;
if (previewMode && (widget.$el.closest('[data-no-preview="true"]').length)) {
// TODO the flag should be fetched through widget params somehow
return;
@@ -2017,7 +2037,7 @@ const SnippetOptionWidget = Widget.extend({
// If it is not preview mode, the user selected the option for good
// (so record the action)
if (!previewMode) {
if (shouldRecordUndo) {
this.trigger_up('request_history_undo_record', {$target: this.$target});
}
@@ -2035,6 +2055,38 @@ const SnippetOptionWidget = Widget.extend({
});
});
}});
// Check linked widgets: force their value and simulate a notification
const triggerWidgetsNames = ev.data.triggerWidgetsNames;
const triggerWidgetsValues = ev.data.triggerWidgetsValues;
for (let i = 0, l = triggerWidgetsNames.length; i < l; i++) {
const widgetName = triggerWidgetsNames[i];
const widgetValue = triggerWidgetsValues[i];
let linkedWidget = null;
this.trigger_up('user_value_widget_request', {
name: widgetName,
onSuccess: _widget => linkedWidget = _widget,
});
if (linkedWidget) {
if (widgetValue !== undefined) {
// FIXME right now only make this work supposing it is a
// colorpicker widget with big big hacks, this should be
// improved a lot
const normValue = this._normalizeWidgetValue(widgetValue);
if (previewMode === true) {
linkedWidget._previewColor = normValue;
} else if (previewMode === false) {
linkedWidget._previewColor = false;
linkedWidget._value = normValue;
} else {
linkedWidget._previewColor = false;
}
}
linkedWidget.notifyValueChange(previewMode, true);
}
}
},
});
const registry = {};