@useinsider/guido 3.20.1 → 3.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Guido.vue.js +1 -1
- package/dist/components/Guido.vue2.js +65 -64
- package/dist/components/organisms/AutoSaveController.vue2.js +10 -9
- package/dist/components/organisms/header/EditorActions.vue.js +4 -4
- package/dist/components/organisms/header/EditorActions.vue2.js +53 -51
- package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +3 -3
- package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +23 -22
- package/dist/composables/useAutoSave.js +46 -44
- package/dist/composables/useLegacyStrategyConversion.js +16 -16
- package/dist/composables/useSave.js +26 -23
- package/dist/composables/useSaveValidation.js +113 -114
- package/dist/composables/useSaveValidationRollout.js +17 -6
- package/dist/composables/useStripo.js +4 -3
- package/dist/extensions/Blocks/Items/block.js +43 -42
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +296 -223
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +221 -203
- package/dist/extensions/Blocks/Recommendation/utils/blockRefresh.js +19 -0
- package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +51 -36
- package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +31 -35
- package/dist/extensions/Blocks/Unsubscribe/block.js +70 -75
- package/dist/guido.css +1 -1
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +271 -192
- package/dist/package.json.js +1 -1
- package/dist/services/settingsApi.js +11 -0
- package/dist/src/components/Guido.vue.d.ts +1 -1
- package/dist/src/components/organisms/header/EditorActions.vue.d.ts +1 -1
- package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -1
- package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -1
- package/dist/src/composables/useAutoSave.d.ts +4 -1
- package/dist/src/composables/useSaveValidationRollout.d.ts +1 -0
- package/dist/src/extensions/Blocks/Checkbox/controls/blockBackground/index.d.ts +1 -0
- package/dist/src/extensions/Blocks/CouponBlock/controls/index.d.ts +8 -0
- package/dist/src/extensions/Blocks/Items/controls/index.d.ts +40 -0
- package/dist/src/extensions/Blocks/RadioButton/controls/blockBackground/index.d.ts +1 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/blockBackground/index.d.ts +1 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/button/index.d.ts +11 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/customAttribute/index.d.ts +7 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/image/index.d.ts +2 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +18 -3
- package/dist/src/extensions/Blocks/Recommendation/controls/name/index.d.ts +7 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/oldPrice/index.d.ts +7 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/omnibusDiscount/index.d.ts +7 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/omnibusPrice/index.d.ts +7 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/price/index.d.ts +7 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/title/index.d.ts +7 -0
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +9 -1
- package/dist/src/extensions/Blocks/Recommendation/utils/blockRefresh.d.ts +17 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/nodeConfigWriter.d.ts +7 -0
- package/dist/src/extensions/Blocks/Unsubscribe/block.d.ts +1 -6
- package/dist/src/extensions/Blocks/_Boilerplate/controls/blockBackground/index.d.ts +1 -0
- package/dist/src/extensions/Blocks/controlFactories.d.ts +22 -0
- package/dist/src/services/settingsApi.d.ts +6 -0
- package/dist/src/stores/setup-settings.d.ts +4 -0
- package/dist/static/styles/components/button.css.js +5 -0
- package/dist/stores/setup-settings.js +10 -0
- package/package.json +4 -4
|
@@ -1,48 +1,56 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var i = (
|
|
4
|
-
import { useConfig as
|
|
5
|
-
import { ModificationDescription as
|
|
6
|
-
import { CommonControl as
|
|
7
|
-
import { RRS_CONFIG_VERSION as
|
|
8
|
-
import { RECOMMENDATION_ID_ATTR as
|
|
9
|
-
import { RecommendationConfigService as
|
|
10
|
-
import { useRecommendationExtensionStore as
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
|
|
36
|
-
|
|
1
|
+
var _ = Object.defineProperty;
|
|
2
|
+
var y = (h, c, e) => c in h ? _(h, c, { enumerable: !0, configurable: !0, writable: !0, value: e }) : h[c] = e;
|
|
3
|
+
var i = (h, c, e) => y(h, typeof c != "symbol" ? c + "" : c, e);
|
|
4
|
+
import { useConfig as g } from "../../../../../composables/useConfig.js";
|
|
5
|
+
import { ModificationDescription as N } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
6
|
+
import { CommonControl as P } from "../../../common-control.js";
|
|
7
|
+
import { RRS_CONFIG_VERSION as R, DEFAULT_NODE_CONFIG as a } from "../../constants/defaultConfig.js";
|
|
8
|
+
import { RECOMMENDATION_ID_ATTR as k } from "../../constants/selectors.js";
|
|
9
|
+
import { RecommendationConfigService as l } from "../../services/configService.js";
|
|
10
|
+
import { useRecommendationExtensionStore as I } from "../../store/recommendation.js";
|
|
11
|
+
import { refreshBlockOutsidePanel as S } from "../../utils/blockRefresh.js";
|
|
12
|
+
import { registerNodeConfigWriter as T, writeBlockConfigOutsidePanel as m, hasEditedConfigChange as b } from "../../utils/nodeConfigWriter.js";
|
|
13
|
+
import { AlgorithmControl as O } from "./algorithm.js";
|
|
14
|
+
import { ALGORITHM_CONTROL_ID as me } from "./algorithm.js";
|
|
15
|
+
import { CurrencyControl as B } from "./currency.js";
|
|
16
|
+
import { CURRENCY_CONTROL_ID as pe } from "./currency.js";
|
|
17
|
+
import { FiltersControl as L } from "./filters.js";
|
|
18
|
+
import { FILTERS_CONTROL_ID as ye } from "./filters.js";
|
|
19
|
+
import { LayoutOrientationControl as E } from "./layoutOrientation.js";
|
|
20
|
+
import { LAYOUT_ORIENTATION_CONTROL_ID as Pe } from "./layoutOrientation.js";
|
|
21
|
+
import { LocaleControl as F } from "./locale.js";
|
|
22
|
+
import { LOCALE_CONTROL_ID as ke } from "./locale.js";
|
|
23
|
+
import { PricePlacementControl as D } from "./pricePlacement.js";
|
|
24
|
+
import { PRICE_PLACEMENT_CONTROL_ID as Se } from "./pricePlacement.js";
|
|
25
|
+
import { ProductCountControl as U } from "./productCount.js";
|
|
26
|
+
import { PRODUCT_COUNT_CONTROL_ID as be } from "./productCount.js";
|
|
27
|
+
import { ProductLayoutControl as v } from "./productLayout.js";
|
|
28
|
+
import { PRODUCT_LAYOUT_CONTROL_ID as Be } from "./productLayout.js";
|
|
29
|
+
import { ShuffleControl as w } from "./shuffle.js";
|
|
30
|
+
import { SHUFFLE_CONTROL_ID as Ee } from "./shuffle.js";
|
|
31
|
+
import { StrategyControl as A } from "./strategy.js";
|
|
32
|
+
import { STRATEGY_CONTROL_ID as De } from "./strategy.js";
|
|
33
|
+
import { setCurrencyAttributes as V, getBlockElement as x, isPartnerManagedBlock as W, updateProductContentInPlace as M, regenerateProductRowsWithStyles as G } from "./utils.js";
|
|
34
|
+
import { adjustProductsToSize as ve, formatProductPrice as we, getCardComposition as Ae, getCurrentLayout as Ve, getMainContainerTbody as xe, regenerateMobileProductRows as We, updatePricesInPlace as Me, updateSingleProductContent as Ge } from "./utils.js";
|
|
35
|
+
import { useDebounceFn as C } from "../../../../../node_modules/@vueuse/shared/index.js";
|
|
36
|
+
const f = "Update recommendation filters", z = "ui-elements-recommendation-block";
|
|
37
|
+
class he extends P {
|
|
37
38
|
constructor() {
|
|
38
39
|
super(...arguments);
|
|
39
|
-
i(this, "store",
|
|
40
|
+
i(this, "store", I());
|
|
40
41
|
i(this, "storeUnsubscription", () => {
|
|
41
42
|
});
|
|
42
43
|
// A config change waiting to reach the node config. Deferred so it can ride the
|
|
43
44
|
// re-render's single apply() — one user action must cost one undo press.
|
|
44
45
|
i(this, "pendingNodeConfigWrite", null);
|
|
45
46
|
i(this, "pendingConfigFlushTimer", null);
|
|
47
|
+
// What the panel still owes the block it watches — finished outside the panel on teardown
|
|
48
|
+
// and block switch. A new generation tells debounced work queued for the old one to stand down.
|
|
49
|
+
i(this, "trackedBlockId", null);
|
|
50
|
+
i(this, "fetchedConfigVersion", 0);
|
|
51
|
+
i(this, "hasUnrenderedProducts", !1);
|
|
52
|
+
i(this, "panelGeneration", 0);
|
|
53
|
+
i(this, "isPanelAlive", !0);
|
|
46
54
|
// Sub-control instances for lifecycle management
|
|
47
55
|
i(this, "algorithmControl", null);
|
|
48
56
|
i(this, "localeControl", null);
|
|
@@ -58,11 +66,14 @@ class at extends N {
|
|
|
58
66
|
/**
|
|
59
67
|
* Debounced product fetch to prevent rapid API calls during config changes
|
|
60
68
|
*/
|
|
61
|
-
i(this, "_debouncedFetchProducts",
|
|
69
|
+
i(this, "_debouncedFetchProducts", C(async (e, t) => {
|
|
70
|
+
if (t !== this.panelGeneration)
|
|
71
|
+
return;
|
|
72
|
+
const o = this._getBlockConfigVersion(e);
|
|
62
73
|
try {
|
|
63
|
-
await this.store.fetchRecommendationProducts();
|
|
74
|
+
await (e === null ? this.store.fetchRecommendationProducts() : this.store.fetchRecommendationProductsForBlock(e)), t === this.panelGeneration && (this.fetchedConfigVersion = Math.max(this.fetchedConfigVersion, o));
|
|
64
75
|
} finally {
|
|
65
|
-
this._scheduleConfigFlush();
|
|
76
|
+
t === this.panelGeneration && this._scheduleConfigFlush();
|
|
66
77
|
}
|
|
67
78
|
}, 500));
|
|
68
79
|
/**
|
|
@@ -76,12 +87,12 @@ class at extends N {
|
|
|
76
87
|
* count. The store pads products to the configured size, so in-place only
|
|
77
88
|
* fails when the size actually changed.
|
|
78
89
|
*/
|
|
79
|
-
i(this, "_debouncedRegenerateWithProducts",
|
|
80
|
-
if (!this.currentNode || !this.api)
|
|
90
|
+
i(this, "_debouncedRegenerateWithProducts", C((e) => {
|
|
91
|
+
if (e !== this.panelGeneration || !this.currentNode || !this.api)
|
|
81
92
|
return;
|
|
82
|
-
const t = this._getRecommendationIdFromNode(this.currentNode),
|
|
83
|
-
if (t === null ||
|
|
84
|
-
this._regenerateWithProducts();
|
|
93
|
+
const t = this._getRecommendationIdFromNode(this.currentNode), o = this.store.currentRecommendationId;
|
|
94
|
+
if (t === null || o === null || t === o || !this.store.blockStates[t]) {
|
|
95
|
+
this.hasUnrenderedProducts = !1, this._regenerateWithProducts();
|
|
85
96
|
return;
|
|
86
97
|
}
|
|
87
98
|
if (this.store.blockStates[t].recommendationProducts.length) {
|
|
@@ -89,13 +100,13 @@ class at extends N {
|
|
|
89
100
|
try {
|
|
90
101
|
this._regenerateWithProducts();
|
|
91
102
|
} finally {
|
|
92
|
-
this.store.setCurrentBlock(
|
|
103
|
+
this.store.setCurrentBlock(o);
|
|
93
104
|
}
|
|
94
105
|
}
|
|
95
106
|
}, 100));
|
|
96
107
|
}
|
|
97
108
|
getId() {
|
|
98
|
-
return
|
|
109
|
+
return z;
|
|
99
110
|
}
|
|
100
111
|
get _subControls() {
|
|
101
112
|
return [
|
|
@@ -112,15 +123,15 @@ class at extends N {
|
|
|
112
123
|
];
|
|
113
124
|
}
|
|
114
125
|
getTemplate() {
|
|
115
|
-
var
|
|
116
|
-
return this.rrsEnabled =
|
|
126
|
+
var e;
|
|
127
|
+
return this.rrsEnabled = g().isFeatureEnabled("reusableRecommendationStrategy"), this._subControls.forEach((t) => {
|
|
117
128
|
var o;
|
|
118
|
-
return (o =
|
|
119
|
-
}), this.algorithmControl = new
|
|
120
|
-
|
|
129
|
+
return (o = t == null ? void 0 : t.onDestroy) == null ? void 0 : o.call(t);
|
|
130
|
+
}), this.algorithmControl = new O(), this.localeControl = new F(), this.currencyControl = new B(), this.productCountControl = new U(), this.productLayoutControl = new v(), this.filtersControl = new L(), this.shuffleControl = new w(), this.pricePlacementControl = new D(), this.layoutOrientationControl = new E(), this.strategyControl = this.rrsEnabled ? new A() : null, this._subControls.forEach((t) => {
|
|
131
|
+
t && (t.api = this.api);
|
|
121
132
|
}), `
|
|
122
133
|
<div class="recommendation-controls-container">
|
|
123
|
-
${((
|
|
134
|
+
${((e = this.strategyControl) == null ? void 0 : e.getTemplate()) ?? ""}
|
|
124
135
|
${this.layoutOrientationControl.getTemplate()}
|
|
125
136
|
${this.productCountControl.getTemplate()}
|
|
126
137
|
${this.productLayoutControl.getTemplate()}
|
|
@@ -133,39 +144,39 @@ class at extends N {
|
|
|
133
144
|
</div>
|
|
134
145
|
`;
|
|
135
146
|
}
|
|
136
|
-
_showControlsForBlock(
|
|
137
|
-
var
|
|
138
|
-
const
|
|
139
|
-
if (!
|
|
147
|
+
_showControlsForBlock(e) {
|
|
148
|
+
var s;
|
|
149
|
+
const t = (s = this.getContainer()) == null ? void 0 : s.querySelector(".recommendation-controls-container");
|
|
150
|
+
if (!t)
|
|
140
151
|
return;
|
|
141
|
-
const o = this._getRecommendationIdFromNode(
|
|
142
|
-
|
|
152
|
+
const o = this._getRecommendationIdFromNode(e) === null ? null : l.getConfig(e), n = this.rrsEnabled && !!o && (!!(o != null && o.strategyId) || ((o == null ? void 0 : o.configVersion) ?? 0) >= R), r = this.rrsEnabled && !!o && !n;
|
|
153
|
+
t.classList.toggle("strategy-block", n), t.classList.toggle("legacy-strategy-block", r);
|
|
143
154
|
}
|
|
144
155
|
async onRender() {
|
|
145
156
|
var o;
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
157
|
+
T(this.api);
|
|
158
|
+
const e = this._getRecommendationIdFromNode(this.currentNode), t = e ?? this.store.currentRecommendationId;
|
|
159
|
+
if (t !== null && this.store.setCurrentBlock(t), e !== null && this._syncNodeConfigIfChanged(e), this._listenStateUpdates(), this._showControlsForBlock(this.currentNode), e !== null && this.strategyControl && (this.strategyControl.api = this.api, this.strategyControl.currentNode = this.currentNode, this.strategyControl.onRender()), t !== null && ((o = this.store.blockStates[t]) != null && o.isInitialized)) {
|
|
149
160
|
this._initializeSubControls();
|
|
150
161
|
return;
|
|
151
162
|
}
|
|
152
|
-
await this._fetchBlockData(
|
|
163
|
+
await this._fetchBlockData(t), this._initializeSubControls();
|
|
153
164
|
}
|
|
154
|
-
onTemplateNodeUpdated(
|
|
165
|
+
onTemplateNodeUpdated(e) {
|
|
155
166
|
var o;
|
|
156
|
-
super.onTemplateNodeUpdated(
|
|
157
|
-
const
|
|
158
|
-
|
|
167
|
+
super.onTemplateNodeUpdated(e);
|
|
168
|
+
const t = this._getRecommendationIdFromNode(e);
|
|
169
|
+
t !== null && t !== this.store.currentRecommendationId && this.store.setCurrentBlock(t), t !== null && this._syncNodeConfigIfChanged(t), this._showControlsForBlock(e), t !== null && !((o = this.store.blockStates[t]) != null && o.isInitialized) && this._fetchBlockData(t).then(() => {
|
|
159
170
|
this._initializeSubControls();
|
|
160
|
-
}), this._subControls.forEach((
|
|
161
|
-
var
|
|
162
|
-
|
|
171
|
+
}), this._subControls.forEach((n) => {
|
|
172
|
+
var r;
|
|
173
|
+
n != null && n.api && (n.currentNode = e, (r = n.onTemplateNodeUpdated) == null || r.call(n, e));
|
|
163
174
|
});
|
|
164
175
|
}
|
|
165
176
|
onDestroy() {
|
|
166
|
-
this.storeUnsubscription(), this.
|
|
167
|
-
var
|
|
168
|
-
return (
|
|
177
|
+
this.panelGeneration++, this.isPanelAlive = !1, this.storeUnsubscription(), this._finishBlockOutsidePanel(), this.hasUnrenderedProducts = !1, this._subControls.forEach((e) => {
|
|
178
|
+
var t;
|
|
179
|
+
return (t = e == null ? void 0 : e.onDestroy) == null ? void 0 : t.call(e);
|
|
169
180
|
});
|
|
170
181
|
}
|
|
171
182
|
/**
|
|
@@ -173,9 +184,9 @@ class at extends N {
|
|
|
173
184
|
* Each sub-control manages its own form values and event listeners
|
|
174
185
|
*/
|
|
175
186
|
_initializeSubControls() {
|
|
176
|
-
this._subControls.forEach((
|
|
177
|
-
var
|
|
178
|
-
|
|
187
|
+
this._subControls.forEach((e) => {
|
|
188
|
+
var t;
|
|
189
|
+
e && (e.api = this.api, e.currentNode = this.currentNode, (t = e.onRender) == null || t.call(e));
|
|
179
190
|
});
|
|
180
191
|
}
|
|
181
192
|
/**
|
|
@@ -202,35 +213,36 @@ class at extends N {
|
|
|
202
213
|
* that state and made a re-dropped saved module keep the defaults its wiped
|
|
203
214
|
* state was rebuilt with (SD-150347).
|
|
204
215
|
*/
|
|
205
|
-
_syncNodeConfigIfChanged(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
216
|
+
_syncNodeConfigIfChanged(e) {
|
|
217
|
+
var r;
|
|
218
|
+
this.pendingNodeConfigWrite && this.pendingNodeConfigWrite.blockId !== e && this._flushPendingNodeConfig();
|
|
219
|
+
const t = this.store.blockStates[e];
|
|
220
|
+
if (!t)
|
|
209
221
|
return;
|
|
210
|
-
const o = JSON.stringify(
|
|
211
|
-
|
|
222
|
+
const o = JSON.stringify(l.getConfig(this.currentNode)), n = t.syncedConfigFingerprint;
|
|
223
|
+
t.syncedConfigFingerprint = o, n !== o && ((r = this.pendingNodeConfigWrite) == null ? void 0 : r.blockId) !== e && this._syncNodeConfigToStore();
|
|
212
224
|
}
|
|
213
225
|
/** Whether the deferred write would move the node's strategyId — see the caller (SD-149916). */
|
|
214
226
|
_isPendingStrategyIdChange() {
|
|
215
|
-
const
|
|
216
|
-
return
|
|
227
|
+
const e = this.pendingNodeConfigWrite;
|
|
228
|
+
return e ? l.getConfig(this.currentNode).strategyId !== e.updates.strategyId : !1;
|
|
217
229
|
}
|
|
218
230
|
_capturePendingNodeConfigWrite() {
|
|
219
|
-
const t = this.store.
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
231
|
+
const e = this.store.currentRecommendationId, t = e === null ? void 0 : this.store.blockStates[e];
|
|
232
|
+
!this.currentNode || !this.api || e === null || !t || (this.pendingNodeConfigWrite = {
|
|
233
|
+
blockId: e,
|
|
234
|
+
updates: this._getNodeConfigUpdates(t.recommendationConfigs)
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
_getNodeConfigUpdates(e) {
|
|
238
|
+
const { filters: t, strategy: o, strategyId: n, size: r, nodeConfigVersion: s } = e, { partnerName: d } = g();
|
|
239
|
+
return {
|
|
240
|
+
filters: t,
|
|
241
|
+
strategy: o,
|
|
242
|
+
strategyId: n,
|
|
243
|
+
size: r,
|
|
244
|
+
configVersion: s,
|
|
245
|
+
...d.value ? { partnerName: d.value } : {}
|
|
234
246
|
};
|
|
235
247
|
}
|
|
236
248
|
/**
|
|
@@ -243,9 +255,9 @@ class at extends N {
|
|
|
243
255
|
* @param documentModifier - The batch to accumulate into
|
|
244
256
|
* @returns Whether anything was staged
|
|
245
257
|
*/
|
|
246
|
-
_stagePendingNodeConfig(
|
|
247
|
-
const
|
|
248
|
-
return !
|
|
258
|
+
_stagePendingNodeConfig(e) {
|
|
259
|
+
const t = this.pendingNodeConfigWrite;
|
|
260
|
+
return !t || !this.currentNode ? !1 : (l.stageConfig(e, this.currentNode, t.updates), !0);
|
|
249
261
|
}
|
|
250
262
|
/**
|
|
251
263
|
* Arms the guaranteed fallback write, once the product fetch has settled. The
|
|
@@ -262,45 +274,54 @@ class at extends N {
|
|
|
262
274
|
}
|
|
263
275
|
/**
|
|
264
276
|
* Writes the deferred change standalone when the batch it was staged into never
|
|
265
|
-
* committed. Always targets
|
|
266
|
-
*
|
|
277
|
+
* committed. Always targets a LIVE node — a captured one is an immutable snapshot
|
|
278
|
+
* the intervening re-render staled, and saveConfig swallows that failure.
|
|
267
279
|
*/
|
|
268
280
|
_flushPendingNodeConfig() {
|
|
269
|
-
const
|
|
270
|
-
if (this.pendingNodeConfigWrite = null, this._clearConfigFlush(), !
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
281
|
+
const e = this.pendingNodeConfigWrite;
|
|
282
|
+
if (this.pendingNodeConfigWrite = null, this._clearConfigFlush(), !(!e || !this.api)) {
|
|
283
|
+
if (e.blockId !== this.store.currentRecommendationId || !this.currentNode) {
|
|
284
|
+
const { blockId: t, updates: o } = e;
|
|
285
|
+
!m(t, o, f) && this.store.blockStates[t] && console.error("[recommendation] pending config write did not reach a node", { blockId: t });
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
b(this.currentNode, e.updates) && l.updateConfig(
|
|
289
|
+
this.api,
|
|
290
|
+
this.currentNode,
|
|
291
|
+
e.updates,
|
|
292
|
+
f
|
|
293
|
+
);
|
|
294
|
+
}
|
|
274
295
|
}
|
|
275
296
|
_syncNodeConfigToStore() {
|
|
276
|
-
var
|
|
277
|
-
const
|
|
297
|
+
var n;
|
|
298
|
+
const e = l.getConfig(this.currentNode), t = this.store.currentRecommendationId, o = t !== null && ((n = this.store.blockStates[t]) == null ? void 0 : n.isInitialized);
|
|
278
299
|
this.store.patchCurrentBlockConfig({
|
|
279
|
-
strategy:
|
|
280
|
-
strategyId:
|
|
281
|
-
nodeConfigVersion:
|
|
282
|
-
language:
|
|
283
|
-
size:
|
|
284
|
-
productIds:
|
|
285
|
-
cardsInRow:
|
|
286
|
-
mobileCardsInRow:
|
|
287
|
-
mobileLayoutEnabled:
|
|
288
|
-
orientation:
|
|
300
|
+
strategy: e.strategy,
|
|
301
|
+
strategyId: e.strategyId,
|
|
302
|
+
nodeConfigVersion: e.configVersion,
|
|
303
|
+
language: e.language,
|
|
304
|
+
size: e.size,
|
|
305
|
+
productIds: e.productIds,
|
|
306
|
+
cardsInRow: e.cardsInRow,
|
|
307
|
+
mobileCardsInRow: e.mobileCardsInRow,
|
|
308
|
+
mobileLayoutEnabled: e.mobileLayoutEnabled,
|
|
309
|
+
orientation: e.layout,
|
|
289
310
|
// Only sync filters from node config during initial load.
|
|
290
311
|
// After initialization, the Pinia store is the source of truth
|
|
291
312
|
// for filters (edited via the filter drawer).
|
|
292
|
-
...o ? {} : { filters:
|
|
293
|
-
shuffleProducts:
|
|
294
|
-
priceMovedToNextLine:
|
|
295
|
-
priceHideIfSameAsDiscounted:
|
|
313
|
+
...o ? {} : { filters: e.filters },
|
|
314
|
+
shuffleProducts: e.shuffleProducts,
|
|
315
|
+
priceMovedToNextLine: e.priceMovedToNextLine,
|
|
316
|
+
priceHideIfSameAsDiscounted: e.priceHideIfSameAsDiscounted,
|
|
296
317
|
currencySettings: {
|
|
297
|
-
name:
|
|
298
|
-
value:
|
|
299
|
-
symbol:
|
|
300
|
-
alignment:
|
|
301
|
-
decimalCount:
|
|
302
|
-
decimalSeparator:
|
|
303
|
-
thousandSeparator:
|
|
318
|
+
name: e.currency.code,
|
|
319
|
+
value: e.currency.code,
|
|
320
|
+
symbol: e.currency.symbol,
|
|
321
|
+
alignment: e.currency.alignment === "before" ? "0" : "1",
|
|
322
|
+
decimalCount: e.currency.decimalCount.toString(),
|
|
323
|
+
decimalSeparator: e.currency.decimalSeparator,
|
|
324
|
+
thousandSeparator: e.currency.thousandSeparator
|
|
304
325
|
}
|
|
305
326
|
}, { triggerRefetch: !1 });
|
|
306
327
|
}
|
|
@@ -313,18 +334,27 @@ class at extends N {
|
|
|
313
334
|
* Shared by onRender() and onTemplateNodeUpdated() to avoid duplication.
|
|
314
335
|
* Marks the block as initialized to prevent redundant fetches on re-selection.
|
|
315
336
|
*/
|
|
316
|
-
async _fetchBlockData(
|
|
317
|
-
|
|
337
|
+
async _fetchBlockData(e) {
|
|
338
|
+
if (e !== null && this.store.markBlockInitialized(e), (await Promise.allSettled([
|
|
318
339
|
this.store.fetchRecommendationCreateData(),
|
|
319
340
|
this.store.fetchRecommendationFilters()
|
|
320
|
-
])).forEach((
|
|
321
|
-
|
|
322
|
-
}), this.
|
|
341
|
+
])).forEach((n, r) => {
|
|
342
|
+
n.status === "rejected" && console.warn(`Recommendation block: ${["fetchRecommendationCreateData", "fetchRecommendationFilters"][r]} failed`, n.reason);
|
|
343
|
+
}), e !== null && this.store.currentRecommendationId !== e) {
|
|
344
|
+
this._refreshOutsidePanel(e, !0);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
this._applySmartDefaults();
|
|
348
|
+
const o = this._getBlockConfigVersion(e);
|
|
323
349
|
try {
|
|
324
350
|
await this.store.fetchRecommendationProducts();
|
|
325
|
-
} catch (
|
|
326
|
-
console.warn("Recommendation block: fetchRecommendationProducts failed",
|
|
351
|
+
} catch (n) {
|
|
352
|
+
console.warn("Recommendation block: fetchRecommendationProducts failed", n);
|
|
327
353
|
}
|
|
354
|
+
e !== null && !this._isPanelOn(e) && this._refreshOutsidePanel(e, this._getBlockConfigVersion(e) !== o);
|
|
355
|
+
}
|
|
356
|
+
_isPanelOn(e) {
|
|
357
|
+
return this.isPanelAlive && this.store.currentRecommendationId === e;
|
|
328
358
|
}
|
|
329
359
|
/**
|
|
330
360
|
* Applies smart defaults for newly dropped blocks.
|
|
@@ -339,39 +369,39 @@ class at extends N {
|
|
|
339
369
|
_applySmartDefaults() {
|
|
340
370
|
if (!this.currentNode || !this.api)
|
|
341
371
|
return;
|
|
342
|
-
const
|
|
343
|
-
let o = null,
|
|
344
|
-
if (
|
|
345
|
-
const { currencyList:
|
|
346
|
-
|
|
347
|
-
(
|
|
348
|
-
) || (o =
|
|
372
|
+
const e = l.getConfig(this.currentNode), t = {};
|
|
373
|
+
let o = null, n = null, r = null;
|
|
374
|
+
if (e.currency.code === a.currency.code) {
|
|
375
|
+
const { currencyList: s } = this.store;
|
|
376
|
+
s.length > 0 && (s.some(
|
|
377
|
+
(u) => u.value === `price.${a.currency.code}`
|
|
378
|
+
) || (o = s[0].value.replace("price.", ""), t.currency = {
|
|
349
379
|
...a.currency,
|
|
350
380
|
code: o,
|
|
351
381
|
symbol: o
|
|
352
382
|
}));
|
|
353
383
|
}
|
|
354
|
-
if (
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
(
|
|
358
|
-
) || (
|
|
384
|
+
if (e.strategy === a.strategy) {
|
|
385
|
+
const s = this.store.getActivePredictiveAlgorithms;
|
|
386
|
+
s.length > 0 && (s.some(
|
|
387
|
+
(u) => u.value === a.strategy
|
|
388
|
+
) || (n = s[0].value, t.strategy = n));
|
|
359
389
|
}
|
|
360
|
-
if (
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
(
|
|
364
|
-
) || (
|
|
390
|
+
if (e.language === a.language) {
|
|
391
|
+
const s = this.store.getLanguages;
|
|
392
|
+
s.length > 0 && (s.some(
|
|
393
|
+
(u) => u.value === a.language
|
|
394
|
+
) || (r = s[0].value, t.language = r));
|
|
365
395
|
}
|
|
366
|
-
!o && !
|
|
396
|
+
!o && !n && !r || (l.updateConfig(
|
|
367
397
|
this.api,
|
|
368
398
|
this.currentNode,
|
|
369
|
-
|
|
399
|
+
t,
|
|
370
400
|
"Applied smart defaults"
|
|
371
|
-
), o &&
|
|
401
|
+
), o && t.currency && V({
|
|
372
402
|
currentNode: this.currentNode,
|
|
373
403
|
documentModifier: this.api.getDocumentModifier(),
|
|
374
|
-
currency:
|
|
404
|
+
currency: t.currency
|
|
375
405
|
}), this.store.patchCurrentBlockConfig({
|
|
376
406
|
...o ? {
|
|
377
407
|
currencySettings: {
|
|
@@ -384,46 +414,88 @@ class at extends N {
|
|
|
384
414
|
thousandSeparator: a.currency.thousandSeparator
|
|
385
415
|
}
|
|
386
416
|
} : {},
|
|
387
|
-
...
|
|
388
|
-
...
|
|
417
|
+
...n ? { strategy: n } : {},
|
|
418
|
+
...r ? { language: r } : {}
|
|
389
419
|
}, { triggerRefetch: !1 }));
|
|
390
420
|
}
|
|
391
421
|
/**
|
|
392
422
|
* Reads the recommendation-id attribute from the block element within the node
|
|
393
423
|
*/
|
|
394
|
-
_getRecommendationIdFromNode(
|
|
395
|
-
const
|
|
396
|
-
if (!
|
|
424
|
+
_getRecommendationIdFromNode(e) {
|
|
425
|
+
const t = x(e);
|
|
426
|
+
if (!t || !("getAttribute" in t))
|
|
397
427
|
return null;
|
|
398
|
-
const o =
|
|
428
|
+
const o = t.getAttribute(k);
|
|
399
429
|
if (!o)
|
|
400
430
|
return null;
|
|
401
|
-
const
|
|
402
|
-
return Number.isNaN(
|
|
431
|
+
const n = parseInt(o);
|
|
432
|
+
return Number.isNaN(n) ? null : n;
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Lands what the panel still owes its block before it stops watching it: the config now, the
|
|
436
|
+
* products through a block-scoped refresh. Never throws — it runs from Stripo's teardown.
|
|
437
|
+
*/
|
|
438
|
+
_finishBlockOutsidePanel({ blockId: e, fetchedConfigVersion: t, hasUnrenderedProducts: o } = this._trackedBlockSnapshot()) {
|
|
439
|
+
try {
|
|
440
|
+
this._flushPendingNodeConfig();
|
|
441
|
+
const n = e === null ? void 0 : this.store.blockStates[e];
|
|
442
|
+
if (e === null || !n)
|
|
443
|
+
return;
|
|
444
|
+
const r = t !== n.configVersion;
|
|
445
|
+
r && !m(
|
|
446
|
+
e,
|
|
447
|
+
this._getNodeConfigUpdates(n.recommendationConfigs),
|
|
448
|
+
f
|
|
449
|
+
) && console.error("[recommendation] config write outside the panel did not reach a node", { blockId: e }), (r || o) && this._refreshOutsidePanel(e, r);
|
|
450
|
+
} catch (n) {
|
|
451
|
+
console.error("[recommendation] finishing the block outside the panel failed", n);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
_trackedBlockSnapshot() {
|
|
455
|
+
return {
|
|
456
|
+
blockId: this.trackedBlockId,
|
|
457
|
+
fetchedConfigVersion: this.fetchedConfigVersion,
|
|
458
|
+
hasUnrenderedProducts: this.hasUnrenderedProducts
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
_refreshOutsidePanel(e, t) {
|
|
462
|
+
S(e, {
|
|
463
|
+
pickUpdates: (o) => this._getNodeConfigUpdates(o),
|
|
464
|
+
description: "Update recommendation configuration",
|
|
465
|
+
fetch: t
|
|
466
|
+
}).then((o) => {
|
|
467
|
+
!o && this.store.blockStates[e] && console.error("[recommendation] refresh outside the panel did not reach a node", { blockId: e });
|
|
468
|
+
}).catch((o) => {
|
|
469
|
+
console.error("[recommendation] refresh outside the panel failed", o);
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
_getBlockConfigVersion(e) {
|
|
473
|
+
var t;
|
|
474
|
+
return e === null ? 0 : ((t = this.store.blockStates[e]) == null ? void 0 : t.configVersion) ?? 0;
|
|
403
475
|
}
|
|
404
476
|
/** Draws the current block's products into this panel's node. */
|
|
405
477
|
_regenerateWithProducts() {
|
|
406
478
|
if (!this.currentNode || !this.api)
|
|
407
479
|
return;
|
|
408
|
-
const
|
|
409
|
-
if (
|
|
410
|
-
o && (
|
|
480
|
+
const e = this.store.recommendationProducts, t = this.api.getDocumentModifier(), o = this._stagePendingNodeConfig(t);
|
|
481
|
+
if (W(this.currentNode)) {
|
|
482
|
+
o && (t.apply(new N("Update recommendation configuration")), this.pendingNodeConfigWrite = null, this._clearConfigFlush());
|
|
411
483
|
return;
|
|
412
484
|
}
|
|
413
|
-
|
|
485
|
+
M({
|
|
414
486
|
currentNode: this.currentNode,
|
|
415
|
-
documentModifier:
|
|
416
|
-
products:
|
|
417
|
-
}) ||
|
|
487
|
+
documentModifier: t,
|
|
488
|
+
products: e
|
|
489
|
+
}) || G({
|
|
418
490
|
currentNode: this.currentNode,
|
|
419
|
-
documentModifier:
|
|
420
|
-
products:
|
|
491
|
+
documentModifier: t,
|
|
492
|
+
products: e
|
|
421
493
|
});
|
|
422
494
|
}
|
|
423
495
|
/**
|
|
424
496
|
* Listen to store changes that require product refresh or regeneration.
|
|
425
497
|
*
|
|
426
|
-
* Uses configVersion counter (
|
|
498
|
+
* Uses the block's configVersion counter (bumped by patchCurrentBlockConfig and legacy conversion)
|
|
427
499
|
* to distinguish user-initiated config changes from internal mutations
|
|
428
500
|
* (e.g., fetchRecommendationCreateData setting preferred currency).
|
|
429
501
|
*
|
|
@@ -434,55 +506,56 @@ class at extends N {
|
|
|
434
506
|
* We skip that tick and update tracking references instead.
|
|
435
507
|
*/
|
|
436
508
|
_listenStateUpdates() {
|
|
437
|
-
const { store:
|
|
438
|
-
let
|
|
439
|
-
this.storeUnsubscription =
|
|
440
|
-
const
|
|
441
|
-
if (
|
|
442
|
-
|
|
509
|
+
const { store: e } = this;
|
|
510
|
+
let t = e.recommendationProducts, o = this._getBlockConfigVersion(e.currentRecommendationId);
|
|
511
|
+
this.panelGeneration++, this.isPanelAlive = !0, this.trackedBlockId = e.currentRecommendationId, this.fetchedConfigVersion = o, this.hasUnrenderedProducts = !1, this.storeUnsubscription = e.$subscribe(() => {
|
|
512
|
+
const n = e.currentRecommendationId;
|
|
513
|
+
if (n !== this.trackedBlockId) {
|
|
514
|
+
const p = this._trackedBlockSnapshot();
|
|
515
|
+
this.panelGeneration++, this.trackedBlockId = n, t = e.recommendationProducts, o = this._getBlockConfigVersion(n), this.fetchedConfigVersion = o, this.hasUnrenderedProducts = !1, this._finishBlockOutsidePanel(p);
|
|
443
516
|
return;
|
|
444
517
|
}
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
const
|
|
448
|
-
d &&
|
|
518
|
+
const r = this._getBlockConfigVersion(n);
|
|
519
|
+
r !== o && (o = r, this._capturePendingNodeConfigWrite(), this._isPendingStrategyIdChange() && this._flushPendingNodeConfig(), this._debouncedFetchProducts(n, this.panelGeneration));
|
|
520
|
+
const s = e.recommendationProducts, d = s !== t, u = Array.isArray(s) && s.length > 0;
|
|
521
|
+
d && u && (t = s, this.hasUnrenderedProducts = !0, this._debouncedRegenerateWithProducts(this.panelGeneration));
|
|
449
522
|
});
|
|
450
523
|
}
|
|
451
524
|
}
|
|
452
525
|
export {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
526
|
+
me as ALGORITHM_CONTROL_ID,
|
|
527
|
+
O as AlgorithmControl,
|
|
528
|
+
z as CONTROL_BLOCK_ID,
|
|
529
|
+
pe as CURRENCY_CONTROL_ID,
|
|
530
|
+
B as CurrencyControl,
|
|
531
|
+
ye as FILTERS_CONTROL_ID,
|
|
532
|
+
L as FiltersControl,
|
|
533
|
+
Pe as LAYOUT_ORIENTATION_CONTROL_ID,
|
|
534
|
+
ke as LOCALE_CONTROL_ID,
|
|
535
|
+
E as LayoutOrientationControl,
|
|
536
|
+
F as LocaleControl,
|
|
537
|
+
Se as PRICE_PLACEMENT_CONTROL_ID,
|
|
538
|
+
be as PRODUCT_COUNT_CONTROL_ID,
|
|
539
|
+
Be as PRODUCT_LAYOUT_CONTROL_ID,
|
|
540
|
+
D as PricePlacementControl,
|
|
541
|
+
U as ProductCountControl,
|
|
542
|
+
v as ProductLayoutControl,
|
|
543
|
+
he as RecommendationBlockControl,
|
|
544
|
+
Ee as SHUFFLE_CONTROL_ID,
|
|
545
|
+
De as STRATEGY_CONTROL_ID,
|
|
546
|
+
w as ShuffleControl,
|
|
547
|
+
A as StrategyControl,
|
|
548
|
+
ve as adjustProductsToSize,
|
|
549
|
+
we as formatProductPrice,
|
|
550
|
+
x as getBlockElement,
|
|
551
|
+
Ae as getCardComposition,
|
|
552
|
+
Ve as getCurrentLayout,
|
|
553
|
+
xe as getMainContainerTbody,
|
|
554
|
+
W as isPartnerManagedBlock,
|
|
555
|
+
We as regenerateMobileProductRows,
|
|
556
|
+
G as regenerateProductRowsWithStyles,
|
|
557
|
+
V as setCurrencyAttributes,
|
|
558
|
+
Me as updatePricesInPlace,
|
|
559
|
+
M as updateProductContentInPlace,
|
|
560
|
+
Ge as updateSingleProductContent
|
|
488
561
|
};
|