@useinsider/guido 3.18.1 → 3.18.2-beta.32d291d
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/README.md +21 -3
- package/dist/@types/config/schemas.js +59 -51
- package/dist/components/Guido.vue.js +4 -4
- package/dist/components/Guido.vue2.js +55 -53
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +7 -7
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +82 -57
- package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.js +18 -0
- package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue2.js +25 -0
- package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +24 -22
- package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +28 -24
- package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.js +21 -0
- package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue2.js +46 -0
- package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +21 -0
- package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +46 -0
- package/dist/components/organisms/save-as-template/SaveAsTemplateDrawer.vue2.js +34 -34
- package/dist/composables/useCustomInterfaceAppearance.js +46 -42
- package/dist/composables/useHttp.js +24 -22
- package/dist/composables/useLegacyStrategyConversion.js +61 -0
- package/dist/enums/extensions/recommendationBlock.js +40 -31
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +91 -84
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +72 -28
- package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +45 -44
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +123 -58
- package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js +42 -0
- package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +7 -7
- package/dist/guido.css +1 -1
- package/dist/node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js +29 -28
- package/dist/package.json.js +1 -1
- package/dist/services/recommendationApi.js +46 -37
- package/dist/services/templateLibraryApi.js +17 -14
- package/dist/src/@types/config/schemas.d.ts +16 -0
- package/dist/src/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.d.ts +2 -0
- package/dist/src/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.d.ts +2 -0
- package/dist/src/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.d.ts +2 -0
- package/dist/src/composables/useConfig.d.ts +4 -0
- package/dist/src/composables/useLegacyStrategyConversion.d.ts +3 -0
- package/dist/src/enums/extensions/recommendationBlock.d.ts +5 -1
- package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +5 -1
- package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +2 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +4 -0
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +82 -1
- package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.d.ts +32 -0
- package/dist/src/services/recommendationApi.d.ts +2 -1
- package/dist/src/stores/config.d.ts +322 -0
- package/dist/src/stores/onboarding.d.ts +808 -10
- package/dist/src/utils/genericUtil.d.ts +6 -0
- package/dist/src/utils/liquidDynamicContent.d.ts +20 -0
- package/dist/static/assets/icons/filled-arrow-rising.svg.js +5 -0
- package/dist/static/assets/icons/line-info.svg.js +5 -0
- package/dist/static/styles/components/recommendation-strategy.css.js +70 -5
- package/dist/stores/config.js +74 -60
- package/dist/stores/onboarding.js +46 -36
- package/dist/utils/genericUtil.js +63 -54
- package/dist/utils/liquidDynamicContent.js +15 -0
- package/dist/utils/templatePreparation.js +54 -52
- package/package.json +3 -3
|
@@ -94,9 +94,9 @@ function j(e, t = {}) {
|
|
|
94
94
|
const u = s ?? P(n), l = y.getConfig(n);
|
|
95
95
|
if (u === "list" || !l.mobileLayoutEnabled)
|
|
96
96
|
return te({ currentNode: n, documentModifier: o });
|
|
97
|
-
const c = A(),
|
|
97
|
+
const c = A(), f = $(r, c.recommendationProducts), a = i ?? U(n, c.filterList), p = `<td><table class="ins-recommendation-product-container ins-recommendation-mobile-container" width="100%" cellpadding="0" cellspacing="0" border="0">${k(f, u, {
|
|
98
98
|
productsPerRow: l.mobileCardsInRow,
|
|
99
|
-
composition:
|
|
99
|
+
composition: a,
|
|
100
100
|
filterList: c.filterList,
|
|
101
101
|
priceInline: !l.priceMovedToNextLine,
|
|
102
102
|
// Match the initial render's gutter so a regeneration never changes block height (SD-143023, #386).
|
|
@@ -122,9 +122,9 @@ function ie(e, t = {}) {
|
|
|
122
122
|
const u = n.querySelector(L) ?? n.querySelector(W);
|
|
123
123
|
if (!u)
|
|
124
124
|
return !1;
|
|
125
|
-
const l = A(), c = $(r, l.recommendationProducts), { cardsInRow:
|
|
126
|
-
productsPerRow:
|
|
127
|
-
composition:
|
|
125
|
+
const l = A(), c = $(r, l.recommendationProducts), { cardsInRow: f } = y.getConfig(n), a = i ?? U(n, l.filterList), d = s ?? P(n), p = y.getConfig(n), E = k(c, d, {
|
|
126
|
+
productsPerRow: f,
|
|
127
|
+
composition: a,
|
|
128
128
|
filterList: l.filterList,
|
|
129
129
|
priceInline: !p.priceMovedToNextLine,
|
|
130
130
|
// Match the initial render's gutter so a regeneration never changes block height (SD-143023, #386).
|
|
@@ -153,10 +153,10 @@ function ce(e, t, n) {
|
|
|
153
153
|
return !1;
|
|
154
154
|
const s = A(), i = r.split(",").filter(Boolean), u = D(i, o, s.filterList), l = [], c = u.join(",") !== i.join(",");
|
|
155
155
|
c && l.push([R, u.join(",")]);
|
|
156
|
-
const
|
|
156
|
+
const f = le(
|
|
157
157
|
o.getAttribute(q)
|
|
158
|
-
),
|
|
159
|
-
if (
|
|
158
|
+
), a = f && z(f, o, s.filterList);
|
|
159
|
+
if (f && a && a.join(",") !== f.join(",") && l.push([q, JSON.stringify(a)]), l.length === 0)
|
|
160
160
|
return !1;
|
|
161
161
|
if (l.forEach(([d, p]) => {
|
|
162
162
|
t.modifyHtml(o).setAttribute(d, p);
|
|
@@ -177,19 +177,20 @@ function Te(e) {
|
|
|
177
177
|
products: r,
|
|
178
178
|
layout: s,
|
|
179
179
|
composition: i,
|
|
180
|
-
skipStylePreservation: u
|
|
180
|
+
skipStylePreservation: u,
|
|
181
|
+
forceApply: l = !1
|
|
181
182
|
} = e;
|
|
182
183
|
if (!t)
|
|
183
184
|
return;
|
|
184
|
-
const
|
|
185
|
+
const c = u ? {} : x(t), f = {
|
|
185
186
|
currentNode: t,
|
|
186
187
|
documentModifier: n,
|
|
187
188
|
products: r,
|
|
188
189
|
layout: s,
|
|
189
190
|
composition: i
|
|
190
191
|
};
|
|
191
|
-
let a = ie(
|
|
192
|
-
a = j(
|
|
192
|
+
let a = ie(f, c);
|
|
193
|
+
a = j(f, c) || a, a && ce(t, n, i), (a || l) && n.apply(new S("Regenerate products with styles")), o == null || o();
|
|
193
194
|
}
|
|
194
195
|
function Re(e, t) {
|
|
195
196
|
return e.length === t ? e : e.length > t ? e.slice(0, t) : [...e, ...H(t - e.length)];
|
|
@@ -250,16 +251,16 @@ function se(e) {
|
|
|
250
251
|
omnibusDiscountEl: l,
|
|
251
252
|
buttonEl: c
|
|
252
253
|
} = e;
|
|
253
|
-
let
|
|
254
|
+
let f = !1;
|
|
254
255
|
if (o && "querySelector" in o) {
|
|
255
|
-
const
|
|
256
|
-
|
|
256
|
+
const a = o.querySelector("img");
|
|
257
|
+
a && (t.modifyHtml(a).setAttribute("src", X(n.image_url)).setAttribute("alt", n.name), f = !0);
|
|
257
258
|
const d = o.querySelector("a");
|
|
258
|
-
d && (t.modifyHtml(d).setAttribute("href", n.url),
|
|
259
|
+
d && (t.modifyHtml(d).setAttribute("href", n.url), f = !0);
|
|
259
260
|
}
|
|
260
261
|
if (r && "querySelector" in r) {
|
|
261
|
-
const
|
|
262
|
-
b(t,
|
|
262
|
+
const a = r.querySelector("strong") ?? r.querySelector("p");
|
|
263
|
+
b(t, a ?? null, n.name) && (f = !0);
|
|
263
264
|
}
|
|
264
265
|
if (K({
|
|
265
266
|
documentModifier: t,
|
|
@@ -268,11 +269,11 @@ function se(e) {
|
|
|
268
269
|
oldPriceEl: i,
|
|
269
270
|
omnibusPriceEl: u,
|
|
270
271
|
omnibusDiscountEl: l
|
|
271
|
-
}) && (
|
|
272
|
-
const
|
|
273
|
-
|
|
272
|
+
}) && (f = !0), c && "querySelector" in c) {
|
|
273
|
+
const a = c.querySelector("a.es-button") || c.querySelector("a");
|
|
274
|
+
a && (t.modifyHtml(a).setAttribute("href", n.url), f = !0);
|
|
274
275
|
}
|
|
275
|
-
return
|
|
276
|
+
return f;
|
|
276
277
|
}
|
|
277
278
|
function V(e) {
|
|
278
279
|
return "querySelector" in e ? e.querySelector(L) ?? e : e;
|
|
@@ -308,14 +309,14 @@ function fe(e, t, n) {
|
|
|
308
309
|
let s = !1;
|
|
309
310
|
return r.forEach((i, u) => {
|
|
310
311
|
const l = Math.min(i.length, n.length);
|
|
311
|
-
i.slice(0, l).forEach((c,
|
|
312
|
+
i.slice(0, l).forEach((c, f) => {
|
|
312
313
|
if (!("querySelector" in c))
|
|
313
314
|
return;
|
|
314
|
-
const
|
|
315
|
-
if (
|
|
315
|
+
const a = ae(u, n[f]);
|
|
316
|
+
if (a === null)
|
|
316
317
|
return;
|
|
317
318
|
const d = c.querySelector("p") ?? null;
|
|
318
|
-
b(t, d,
|
|
319
|
+
b(t, d, a) && (s = !0);
|
|
319
320
|
});
|
|
320
321
|
}), s;
|
|
321
322
|
}
|
|
@@ -336,9 +337,9 @@ function O(e, t, n) {
|
|
|
336
337
|
`[esd-extension-block-id="${m.OMNIBUS_DISCOUNT}"]`
|
|
337
338
|
), c = e.querySelectorAll(
|
|
338
339
|
`[esd-extension-block-id="${m.BUTTON}"]`
|
|
339
|
-
),
|
|
340
|
-
let
|
|
341
|
-
for (let d = 0; d <
|
|
340
|
+
), f = Math.min(o.length, n.length);
|
|
341
|
+
let a = !1;
|
|
342
|
+
for (let d = 0; d < f; d++) {
|
|
342
343
|
const p = se({
|
|
343
344
|
documentModifier: t,
|
|
344
345
|
product: n[d],
|
|
@@ -350,33 +351,33 @@ function O(e, t, n) {
|
|
|
350
351
|
omnibusDiscountEl: l[d] ?? null,
|
|
351
352
|
buttonEl: c[d] ?? null
|
|
352
353
|
});
|
|
353
|
-
|
|
354
|
+
a = a || p;
|
|
354
355
|
}
|
|
355
|
-
return fe(e, t, n) && (
|
|
356
|
+
return fe(e, t, n) && (a = !0), a;
|
|
356
357
|
}
|
|
357
358
|
function qe(e) {
|
|
358
|
-
const { currentNode: t, documentModifier: n, products: o } = e;
|
|
359
|
+
const { currentNode: t, documentModifier: n, products: o, forceApply: r = !1 } = e;
|
|
359
360
|
if (!t || !("querySelectorAll" in t))
|
|
360
361
|
return !1;
|
|
361
|
-
const
|
|
362
|
-
if (!("querySelectorAll" in
|
|
362
|
+
const s = V(t);
|
|
363
|
+
if (!("querySelectorAll" in s) || s.querySelectorAll(
|
|
363
364
|
`[esd-extension-block-id="${m.IMAGE}"]`
|
|
364
365
|
).length !== o.length)
|
|
365
366
|
return !1;
|
|
366
|
-
let
|
|
367
|
-
const
|
|
368
|
-
if (
|
|
369
|
-
const
|
|
370
|
-
if (
|
|
367
|
+
let u = O(s, n, o);
|
|
368
|
+
const l = P(t), c = y.getConfig(t);
|
|
369
|
+
if (l !== "list" && c.mobileLayoutEnabled && "querySelector" in t) {
|
|
370
|
+
const f = t.querySelector(N);
|
|
371
|
+
if (f) {
|
|
371
372
|
const a = O(
|
|
372
|
-
|
|
373
|
+
f,
|
|
373
374
|
n,
|
|
374
375
|
o
|
|
375
376
|
);
|
|
376
|
-
|
|
377
|
+
u = u || a;
|
|
377
378
|
}
|
|
378
379
|
}
|
|
379
|
-
return
|
|
380
|
+
return (u || r) && n.apply(new S("Updated product content in-place")), !0;
|
|
380
381
|
}
|
|
381
382
|
function _(e, t, n) {
|
|
382
383
|
if (!("querySelectorAll" in e))
|
|
@@ -417,8 +418,8 @@ function Me(e) {
|
|
|
417
418
|
if (u !== "list" && l.mobileLayoutEnabled && "querySelector" in t) {
|
|
418
419
|
const c = t.querySelector(N);
|
|
419
420
|
if (c) {
|
|
420
|
-
const
|
|
421
|
-
i = i ||
|
|
421
|
+
const f = _(c, n, r);
|
|
422
|
+
i = i || f;
|
|
422
423
|
}
|
|
423
424
|
}
|
|
424
425
|
return i && n.apply(new S("Updated price formatting in-place")), i;
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import { getRecommendationFeedSourceMaps as
|
|
1
|
+
import { getRecommendationFeedSourceMaps as R, getOperatorOptions as F, PriceAttributes as P } from "../../../../enums/extensions/recommendationBlock.js";
|
|
2
2
|
import { useRecommendationApi as D } from "../../../../services/recommendationApi.js";
|
|
3
|
-
import { useConfigStore as
|
|
4
|
-
import { defineStore as
|
|
3
|
+
import { useConfigStore as k } from "../../../../stores/config.js";
|
|
4
|
+
import { defineStore as L } from "pinia";
|
|
5
5
|
import "../constants/selectors.js";
|
|
6
|
-
import { DEFAULT_MOBILE_CARDS_IN_ROW as
|
|
7
|
-
import { DEFAULT_NODE_CONFIG as N, EXCLUDED_ALGORITHM_IDS as
|
|
8
|
-
import { getDefaultProducts as
|
|
9
|
-
import { generateCompleteFilterQuery as
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
import { DEFAULT_MOBILE_CARDS_IN_ROW as U, DEFAULT_CARDS_IN_ROW as _ } from "../constants/layout.js";
|
|
7
|
+
import { CURRENT_CONFIG_VERSION as y, DEFAULT_NODE_CONFIG as N, EXCLUDED_ALGORITHM_IDS as M } from "../constants/defaultConfig.js";
|
|
8
|
+
import { getDefaultProducts as C } from "../templates/utils.js";
|
|
9
|
+
import { generateCompleteFilterQuery as v } from "../utils/filterUtil.js";
|
|
10
|
+
import { isLegacyStrategyConfig as x } from "../utils/legacyStrategyMigration.js";
|
|
11
|
+
import { getPartnerRecommendationParams as B } from "../utils/partnerCustomizations.js";
|
|
12
|
+
import { sanitizeProductIds as z } from "../utils/productIds.js";
|
|
13
|
+
import { isFilterValid as A } from "../validation/filterSchema.js";
|
|
14
|
+
import { isConfigValid as O } from "../validation/requiredFields.js";
|
|
15
|
+
const m = D();
|
|
16
|
+
let f = null, g = null, h = null, S = null;
|
|
16
17
|
const p = /* @__PURE__ */ new Map();
|
|
17
|
-
function
|
|
18
|
+
function G() {
|
|
18
19
|
return {
|
|
19
|
-
cardsInRow:
|
|
20
|
+
cardsInRow: _,
|
|
20
21
|
currencySettings: {
|
|
21
22
|
name: "USD",
|
|
22
23
|
value: "USD",
|
|
@@ -30,7 +31,7 @@ function w() {
|
|
|
30
31
|
productIds: [],
|
|
31
32
|
id: 1,
|
|
32
33
|
language: "en_US",
|
|
33
|
-
mobileCardsInRow:
|
|
34
|
+
mobileCardsInRow: U,
|
|
34
35
|
mobileLayoutEnabled: !1,
|
|
35
36
|
orientation: "grid",
|
|
36
37
|
recommendedProducts: [],
|
|
@@ -38,6 +39,7 @@ function w() {
|
|
|
38
39
|
shuffleProducts: !1,
|
|
39
40
|
strategy: "mostPopular",
|
|
40
41
|
strategyId: "",
|
|
42
|
+
nodeConfigVersion: y,
|
|
41
43
|
textTrimming: !0,
|
|
42
44
|
unresponsive: !1,
|
|
43
45
|
size: "6",
|
|
@@ -46,20 +48,23 @@ function w() {
|
|
|
46
48
|
priceHideIfSameAsDiscounted: !1
|
|
47
49
|
};
|
|
48
50
|
}
|
|
49
|
-
function
|
|
51
|
+
function w() {
|
|
50
52
|
return {
|
|
51
|
-
recommendationConfigs:
|
|
53
|
+
recommendationConfigs: G(),
|
|
52
54
|
recommendationProducts: [],
|
|
53
55
|
filterStatus: !1,
|
|
54
56
|
filterSelectionDrawerStatus: !1,
|
|
55
57
|
assignStrategyDrawerStatus: !1,
|
|
56
58
|
removeStrategyModalStatus: !1,
|
|
59
|
+
legacyStrategyUpdatedModalStatus: !1,
|
|
57
60
|
filterGroup: 1,
|
|
58
61
|
isInitialized: !1,
|
|
59
|
-
filterSnapshot: null
|
|
62
|
+
filterSnapshot: null,
|
|
63
|
+
syncedConfigFingerprint: null,
|
|
64
|
+
legacyConversionLoading: !1
|
|
60
65
|
};
|
|
61
66
|
}
|
|
62
|
-
const
|
|
67
|
+
const E = () => ({
|
|
63
68
|
recommendationCampaignUrls: {},
|
|
64
69
|
activePredictiveAlgorithms: [],
|
|
65
70
|
languages: {},
|
|
@@ -71,8 +76,8 @@ const z = () => ({
|
|
|
71
76
|
blockStates: {},
|
|
72
77
|
currentRecommendationId: null,
|
|
73
78
|
configVersion: 0
|
|
74
|
-
}),
|
|
75
|
-
state: () =>
|
|
79
|
+
}), et = L("guidoRecommendationExtension", {
|
|
80
|
+
state: () => E(),
|
|
76
81
|
getters: {
|
|
77
82
|
// ====================================================================
|
|
78
83
|
// Proxy Getters — Backward Compatible Access to Current Block State
|
|
@@ -82,7 +87,7 @@ const z = () => ({
|
|
|
82
87
|
* This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
|
|
83
88
|
*/
|
|
84
89
|
recommendationConfigs(t) {
|
|
85
|
-
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs :
|
|
90
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : G();
|
|
86
91
|
},
|
|
87
92
|
/**
|
|
88
93
|
* Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
|
|
@@ -102,6 +107,15 @@ const z = () => ({
|
|
|
102
107
|
removeStrategyModalStatus(t) {
|
|
103
108
|
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].removeStrategyModalStatus : !1;
|
|
104
109
|
},
|
|
110
|
+
isLegacyStrategyBlock() {
|
|
111
|
+
return k().isFeatureEnabled("reusableRecommendationStrategy") && x(this.recommendationConfigs);
|
|
112
|
+
},
|
|
113
|
+
legacyConversionLoading(t) {
|
|
114
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].legacyConversionLoading : !1;
|
|
115
|
+
},
|
|
116
|
+
legacyStrategyUpdatedModalStatus(t) {
|
|
117
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].legacyStrategyUpdatedModalStatus : !1;
|
|
118
|
+
},
|
|
105
119
|
assignedStrategy(t) {
|
|
106
120
|
const { strategyId: e } = this.recommendationConfigs;
|
|
107
121
|
return e ? t.strategies.find((r) => String(r.strategy_id) === e) ?? null : null;
|
|
@@ -137,8 +151,8 @@ const z = () => ({
|
|
|
137
151
|
return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
|
|
138
152
|
},
|
|
139
153
|
getActivePredictiveAlgorithms: (t) => {
|
|
140
|
-
const e =
|
|
141
|
-
return t.activePredictiveAlgorithms.filter((n) => !
|
|
154
|
+
const e = R(), r = [];
|
|
155
|
+
return t.activePredictiveAlgorithms.filter((n) => !M.includes(n)).forEach((n) => {
|
|
142
156
|
r.push(...e.filter((s) => s.id === n));
|
|
143
157
|
}), r.map((n) => ({
|
|
144
158
|
text: n.name,
|
|
@@ -156,7 +170,7 @@ const z = () => ({
|
|
|
156
170
|
getFilterList() {
|
|
157
171
|
return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
|
|
158
172
|
let e;
|
|
159
|
-
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` :
|
|
173
|
+
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : P.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
|
|
160
174
|
text: t.displayName,
|
|
161
175
|
value: e,
|
|
162
176
|
type: t.attributeType
|
|
@@ -178,7 +192,7 @@ const z = () => ({
|
|
|
178
192
|
setCurrentBlock(t) {
|
|
179
193
|
this.blockStates[t] || (this.blockStates = {
|
|
180
194
|
...this.blockStates,
|
|
181
|
-
[t]:
|
|
195
|
+
[t]: w()
|
|
182
196
|
}), this.currentRecommendationId = t;
|
|
183
197
|
},
|
|
184
198
|
/**
|
|
@@ -241,12 +255,12 @@ const z = () => ({
|
|
|
241
255
|
const r = (o, c) => o === "." || o === "," || o === " " ? o : c, n = {
|
|
242
256
|
name: e.currencyCode,
|
|
243
257
|
value: e.currencyCode,
|
|
244
|
-
symbol: e.
|
|
258
|
+
symbol: e.currencySymbol,
|
|
245
259
|
alignment: e.currencyAlignment === "before" ? "0" : "1",
|
|
246
260
|
decimalCount: String(e.currencyDecimalCount),
|
|
247
261
|
decimalSeparator: r(e.currencyDecimalSeparator, ","),
|
|
248
262
|
thousandSeparator: r(e.currencyThousandSeparator, ".")
|
|
249
|
-
}, s = !this.blockStates[t], i = s ?
|
|
263
|
+
}, s = !this.blockStates[t], i = s ? w() : this.blockStates[t];
|
|
250
264
|
i.recommendationConfigs = {
|
|
251
265
|
...i.recommendationConfigs,
|
|
252
266
|
strategy: e.strategy,
|
|
@@ -285,7 +299,7 @@ const z = () => ({
|
|
|
285
299
|
* Creates a filter with the first available attribute and operator pre-selected.
|
|
286
300
|
*/
|
|
287
301
|
createDefaultFilter(t, e) {
|
|
288
|
-
const [r] = this.getFilterList, [n] =
|
|
302
|
+
const [r] = this.getFilterList, [n] = F(r == null ? void 0 : r.type);
|
|
289
303
|
return {
|
|
290
304
|
type: "standardFilter",
|
|
291
305
|
attribute: (r == null ? void 0 : r.value) ?? "",
|
|
@@ -338,6 +352,12 @@ const z = () => ({
|
|
|
338
352
|
closeAssignStrategyDrawer() {
|
|
339
353
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !1);
|
|
340
354
|
},
|
|
355
|
+
openLegacyStrategyUpdatedModal() {
|
|
356
|
+
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].legacyStrategyUpdatedModalStatus = !0);
|
|
357
|
+
},
|
|
358
|
+
closeLegacyStrategyUpdatedModal() {
|
|
359
|
+
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].legacyStrategyUpdatedModalStatus = !1);
|
|
360
|
+
},
|
|
341
361
|
openRemoveStrategyModal() {
|
|
342
362
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !0);
|
|
343
363
|
},
|
|
@@ -352,7 +372,7 @@ const z = () => ({
|
|
|
352
372
|
S = (async () => {
|
|
353
373
|
this.strategiesLoading = !0;
|
|
354
374
|
try {
|
|
355
|
-
this.strategies = await
|
|
375
|
+
this.strategies = await m.fetchRecommendationStrategies();
|
|
356
376
|
} finally {
|
|
357
377
|
this.strategiesLoading = !1;
|
|
358
378
|
}
|
|
@@ -367,7 +387,7 @@ const z = () => ({
|
|
|
367
387
|
const r = typeof t.updated_at == "string" ? t.updated_at : "", n = r ? `${t.strategy_id}:${r}:${e}` : "", s = n ? this.strategyUrlTemplates[n] : void 0;
|
|
368
388
|
if (s)
|
|
369
389
|
return s;
|
|
370
|
-
const { full_path: i = "" } = await
|
|
390
|
+
const { full_path: i = "" } = await m.generateStrategyEndpoint(t, e) ?? {};
|
|
371
391
|
return n && i && (this.strategyUrlTemplates = {
|
|
372
392
|
...this.strategyUrlTemplates,
|
|
373
393
|
[n]: i
|
|
@@ -379,8 +399,44 @@ const z = () => ({
|
|
|
379
399
|
...t.size !== void 0 ? { size: String(t.size) } : {}
|
|
380
400
|
});
|
|
381
401
|
},
|
|
402
|
+
async convertLegacyStrategy(t, e = { scope: "campaign" }) {
|
|
403
|
+
const r = this.currentRecommendationId;
|
|
404
|
+
if (r === null || !this.blockStates[r])
|
|
405
|
+
throw new Error("[Guido] convertLegacyStrategy called without an active block");
|
|
406
|
+
this.blockStates[r].legacyConversionLoading = !0;
|
|
407
|
+
try {
|
|
408
|
+
const n = await m.migrateLegacyStrategy(t, e);
|
|
409
|
+
try {
|
|
410
|
+
await this.fetchStrategies();
|
|
411
|
+
} catch (o) {
|
|
412
|
+
console.error("[Guido] strategy listing refresh after conversion failed", o);
|
|
413
|
+
}
|
|
414
|
+
const s = this.strategies.find((o) => String(o.strategy_id) === n), i = this.blockStates[r];
|
|
415
|
+
return i && (i.recommendationConfigs = {
|
|
416
|
+
...i.recommendationConfigs,
|
|
417
|
+
strategyId: n,
|
|
418
|
+
nodeConfigVersion: y,
|
|
419
|
+
...(s == null ? void 0 : s.size) !== void 0 ? { size: String(s.size) } : {}
|
|
420
|
+
}), this.currentRecommendationId === r && this.configVersion++, n;
|
|
421
|
+
} finally {
|
|
422
|
+
this.blockStates[r] && (this.blockStates[r].legacyConversionLoading = !1);
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
/**
|
|
426
|
+
* Undoes the config half of a conversion whose document write never landed, so the
|
|
427
|
+
* panel and the drawer fall back to "Legacy Strategy" instead of showing an assignment
|
|
428
|
+
* the document never received.
|
|
429
|
+
*/
|
|
430
|
+
revertLegacyConversion(t, e) {
|
|
431
|
+
const r = this.blockStates[t];
|
|
432
|
+
r && (r.recommendationConfigs = { ...r.recommendationConfigs, ...e }, this.currentRecommendationId === t && this.configVersion++);
|
|
433
|
+
},
|
|
382
434
|
removeStrategy() {
|
|
383
|
-
this.patchCurrentBlockConfig({
|
|
435
|
+
this.patchCurrentBlockConfig({
|
|
436
|
+
strategyId: "",
|
|
437
|
+
size: N.size,
|
|
438
|
+
nodeConfigVersion: y
|
|
439
|
+
});
|
|
384
440
|
},
|
|
385
441
|
// ====================================================================
|
|
386
442
|
// Shared Data Fetching (fetched once, used by all blocks)
|
|
@@ -396,7 +452,7 @@ const z = () => ({
|
|
|
396
452
|
activePredictiveAlgorithms: t,
|
|
397
453
|
languages: e,
|
|
398
454
|
currencies: r
|
|
399
|
-
} = await
|
|
455
|
+
} = await m.fetchRecommendationCreateData();
|
|
400
456
|
if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
|
|
401
457
|
const n = this.blockStates[this.currentRecommendationId];
|
|
402
458
|
n.filterStatus = !!n.recommendationConfigs.filters.length;
|
|
@@ -412,18 +468,18 @@ const z = () => ({
|
|
|
412
468
|
},
|
|
413
469
|
async fetchRecommendationFilters() {
|
|
414
470
|
if (!Object.keys(this.filterList).length) {
|
|
415
|
-
if (
|
|
416
|
-
await
|
|
471
|
+
if (g) {
|
|
472
|
+
await g;
|
|
417
473
|
return;
|
|
418
474
|
}
|
|
419
|
-
|
|
420
|
-
const t = await
|
|
475
|
+
g = (async () => {
|
|
476
|
+
const t = await m.fetchRecommendationFilters();
|
|
421
477
|
this.filterList = t;
|
|
422
478
|
})();
|
|
423
479
|
try {
|
|
424
|
-
await
|
|
480
|
+
await g;
|
|
425
481
|
} finally {
|
|
426
|
-
|
|
482
|
+
g = null;
|
|
427
483
|
}
|
|
428
484
|
}
|
|
429
485
|
},
|
|
@@ -452,7 +508,7 @@ const z = () => ({
|
|
|
452
508
|
const n = [...e.recommendationConfigs.filters];
|
|
453
509
|
n[r] = {
|
|
454
510
|
...t,
|
|
455
|
-
isValid:
|
|
511
|
+
isValid: A(t)
|
|
456
512
|
}, e.recommendationConfigs.filters = n;
|
|
457
513
|
}
|
|
458
514
|
},
|
|
@@ -490,7 +546,7 @@ const z = () => ({
|
|
|
490
546
|
}), e.recommendationConfigs.filters = r;
|
|
491
547
|
},
|
|
492
548
|
generateFilterQuery() {
|
|
493
|
-
return
|
|
549
|
+
return v(this.recommendationConfigs.filters);
|
|
494
550
|
},
|
|
495
551
|
/**
|
|
496
552
|
* Validation-only check invoked at save-CTA time. Defined as an action
|
|
@@ -498,33 +554,33 @@ const z = () => ({
|
|
|
498
554
|
* every block's recommendationConfigs across user edits.
|
|
499
555
|
*/
|
|
500
556
|
hasInvalidBlock() {
|
|
501
|
-
return Object.values(this.blockStates).some((t) => !
|
|
557
|
+
return Object.values(this.blockStates).some((t) => !O(t.recommendationConfigs, this));
|
|
502
558
|
},
|
|
503
559
|
// ====================================================================
|
|
504
560
|
// Per-Block Product Fetching
|
|
505
561
|
// ====================================================================
|
|
506
562
|
async fetchRecommendationProducts() {
|
|
507
563
|
if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
|
|
508
|
-
if (
|
|
509
|
-
await
|
|
564
|
+
if (h) {
|
|
565
|
+
await h;
|
|
510
566
|
return;
|
|
511
567
|
}
|
|
512
|
-
|
|
568
|
+
h = this._doFetchProducts();
|
|
513
569
|
try {
|
|
514
|
-
await
|
|
570
|
+
await h;
|
|
515
571
|
} finally {
|
|
516
|
-
|
|
572
|
+
h = null;
|
|
517
573
|
}
|
|
518
574
|
}
|
|
519
575
|
},
|
|
520
576
|
async _doFetchProducts() {
|
|
521
577
|
var d;
|
|
522
|
-
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n =
|
|
578
|
+
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = k();
|
|
523
579
|
if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
|
|
524
580
|
await this._doFetchStrategyProducts(t);
|
|
525
581
|
return;
|
|
526
582
|
}
|
|
527
|
-
const s = r.filters.filter((
|
|
583
|
+
const s = r.filters.filter((u) => u.isValid), i = v(s), o = ((d = R().find((u) => u.key === r.strategy)) == null ? void 0 : d.path) || "", c = parseInt(r.size) || 6, a = {
|
|
528
584
|
locale: r.language,
|
|
529
585
|
currency: r.currencySettings.value,
|
|
530
586
|
partnerName: n.partnerName,
|
|
@@ -532,18 +588,27 @@ const z = () => ({
|
|
|
532
588
|
details: !0,
|
|
533
589
|
campaignId: n.variationId
|
|
534
590
|
};
|
|
535
|
-
r.strategy === "manualMerchandising" ? a.productId =
|
|
591
|
+
r.strategy === "manualMerchandising" ? a.productId = z(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), i && (a.filter = i), r.shuffleProducts && (a.shuffle = !0), Object.assign(
|
|
536
592
|
a,
|
|
537
|
-
|
|
593
|
+
B(n.partnerName, r.strategy)
|
|
538
594
|
);
|
|
539
595
|
let l;
|
|
540
596
|
try {
|
|
541
|
-
l = await
|
|
597
|
+
l = await m.fetchRecommendationProducts(o, a);
|
|
542
598
|
} catch {
|
|
543
599
|
l = [];
|
|
544
600
|
}
|
|
545
601
|
this._setBlockProducts(t, l, c);
|
|
546
602
|
},
|
|
603
|
+
/**
|
|
604
|
+
* Block-scoped counterpart of `fetchRecommendationProducts`, which only ever serves the
|
|
605
|
+
* selected block. The legacy conversion must refresh the products of the block that
|
|
606
|
+
* started it even after the user selected another one.
|
|
607
|
+
*/
|
|
608
|
+
async fetchStrategyProductsForBlock(t) {
|
|
609
|
+
var e;
|
|
610
|
+
(e = this.blockStates[t]) != null && e.recommendationConfigs.strategyId && await this._doFetchStrategyProducts(t);
|
|
611
|
+
},
|
|
547
612
|
async _doFetchStrategyProducts(t) {
|
|
548
613
|
const e = (p.get(t) ?? 0) + 1;
|
|
549
614
|
p.set(t, e);
|
|
@@ -556,8 +621,8 @@ const z = () => ({
|
|
|
556
621
|
);
|
|
557
622
|
if (i) {
|
|
558
623
|
s = parseInt(String(i.size ?? "")) || s;
|
|
559
|
-
const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), d = l === -1 ? a : a.slice(0, l),
|
|
560
|
-
|
|
624
|
+
const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), d = l === -1 ? a : a.slice(0, l), u = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((I) => I && !I.startsWith("user_id=")), b = u.length ? `${d}?${u.join("&")}` : d;
|
|
625
|
+
b && (n = await m.fetchRecommendationProductsByUrl(b));
|
|
561
626
|
}
|
|
562
627
|
} catch {
|
|
563
628
|
n = [];
|
|
@@ -567,14 +632,14 @@ const z = () => ({
|
|
|
567
632
|
_setBlockProducts(t, e, r) {
|
|
568
633
|
if (!this.blockStates[t])
|
|
569
634
|
return;
|
|
570
|
-
const n = e.length > 0 ? e :
|
|
635
|
+
const n = e.length > 0 ? e : C(r);
|
|
571
636
|
this.blockStates[t].recommendationProducts = [
|
|
572
637
|
...n.slice(0, r),
|
|
573
|
-
...
|
|
638
|
+
...C(Math.max(0, r - n.length))
|
|
574
639
|
];
|
|
575
640
|
}
|
|
576
641
|
}
|
|
577
642
|
});
|
|
578
643
|
export {
|
|
579
|
-
|
|
644
|
+
et as useRecommendationExtensionStore
|
|
580
645
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import "../constants/selectors.js";
|
|
2
|
+
import { CURRENT_CONFIG_VERSION as m } from "../constants/defaultConfig.js";
|
|
3
|
+
import { sanitizeProductIds as p } from "./productIds.js";
|
|
4
|
+
const d = "manualMerchandising";
|
|
5
|
+
function N({ strategyId: e, nodeConfigVersion: t }) {
|
|
6
|
+
return !e && t < m;
|
|
7
|
+
}
|
|
8
|
+
const o = (e) => {
|
|
9
|
+
const t = String(e ?? "").trim();
|
|
10
|
+
return /^[1-9]\d*$/.test(t) ? t : null;
|
|
11
|
+
};
|
|
12
|
+
function f({ campaignId: e, templateLibraryId: t }) {
|
|
13
|
+
if (o(e))
|
|
14
|
+
return { scope: "campaign" };
|
|
15
|
+
const n = o(t);
|
|
16
|
+
return n ? { scope: "template", templateId: n } : { scope: "campaign" };
|
|
17
|
+
}
|
|
18
|
+
function y({
|
|
19
|
+
blockId: e,
|
|
20
|
+
url: t,
|
|
21
|
+
campaignId: n,
|
|
22
|
+
variationId: a,
|
|
23
|
+
strategy: c,
|
|
24
|
+
productIds: s,
|
|
25
|
+
target: r
|
|
26
|
+
}) {
|
|
27
|
+
const i = c === d ? p(s).split(",").filter(Boolean) : [];
|
|
28
|
+
return {
|
|
29
|
+
...r.scope === "template" ? { templateId: Number.parseInt(r.templateId) } : {
|
|
30
|
+
campaignId: Number.parseInt(n) || 0,
|
|
31
|
+
variationId: Number.parseInt(a) || 0
|
|
32
|
+
},
|
|
33
|
+
blockId: String(e),
|
|
34
|
+
url: t,
|
|
35
|
+
...i.length ? { productIds: i } : {}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
y as buildLegacyMigrationPayload,
|
|
40
|
+
N as isLegacyStrategyConfig,
|
|
41
|
+
f as resolveMigrationTarget
|
|
42
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ModificationDescription as f } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
2
2
|
import { RECOMMENDATION_ID_ATTR as m } from "../constants/selectors.js";
|
|
3
|
-
import { isPartnerManagedBlock as
|
|
4
|
-
import { RecommendationConfigService as
|
|
3
|
+
import { isPartnerManagedBlock as l, updateProductContentInPlace as a, regenerateProductRowsWithStyles as d } from "../controls/main/utils.js";
|
|
4
|
+
import { RecommendationConfigService as p } from "../services/configService.js";
|
|
5
5
|
let e = null;
|
|
6
|
-
function
|
|
6
|
+
function M(r) {
|
|
7
7
|
e = r;
|
|
8
8
|
}
|
|
9
|
-
function
|
|
9
|
+
function N(r, c, i, u) {
|
|
10
10
|
const n = e == null ? void 0 : e.getDocumentRootHtmlNode();
|
|
11
11
|
if (!e || !n || !("querySelector" in n))
|
|
12
12
|
return !1;
|
|
@@ -14,9 +14,9 @@ function D(r, c, i, u) {
|
|
|
14
14
|
if (!t)
|
|
15
15
|
return !1;
|
|
16
16
|
const o = e.getDocumentModifier();
|
|
17
|
-
return
|
|
17
|
+
return p.stageConfig(o, t, c), l(t) ? (o.apply(new f(u)), !0) : (a({ currentNode: t, documentModifier: o, products: i, forceApply: !0 }) || d({ currentNode: t, documentModifier: o, products: i, forceApply: !0 }), !0);
|
|
18
18
|
}
|
|
19
19
|
export {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
N as commitBlockChangeOutsidePanel,
|
|
21
|
+
M as registerNodeConfigWriter
|
|
22
22
|
};
|