@useinsider/guido 3.18.3-beta.ec88281 → 3.19.0-beta.f02eaa1
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 +41 -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 +53 -49
- 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/composables/useCustomInterfaceAppearance.js +46 -42
- package/dist/composables/useGuidoStateBridge.js +29 -24
- package/dist/composables/useLegacyStrategyConversion.js +61 -0
- package/dist/composables/useStripo.js +7 -7
- package/dist/enums/extensions/recommendationBlock.js +40 -31
- package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +4 -4
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +77 -76
- 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/recommendation.css.js +6 -3
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +110 -46
- 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/library.js +15 -13
- package/dist/package.json.js +1 -1
- package/dist/public/editorState.js +4 -0
- package/dist/services/recommendationApi.js +46 -37
- 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/useGuidoStateBridge.d.ts +11 -7
- 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/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 +70 -1
- package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.d.ts +32 -0
- package/dist/src/library.d.ts +2 -0
- package/dist/src/public/editorState.d.ts +14 -0
- package/dist/src/public/trackingIds.d.ts +6 -2
- package/dist/src/services/recommendationApi.d.ts +2 -1
- package/dist/src/stores/config.d.ts +322 -0
- package/dist/src/stores/editor.d.ts +25 -0
- package/dist/src/stores/guido-email-editor.d.ts +27 -27
- package/dist/src/stores/onboarding.d.ts +808 -10
- 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/editor.js +4 -0
- package/dist/stores/guido-email-editor.js +0 -4
- package/dist/stores/onboarding.js +46 -36
- package/dist/utils/genericUtil.js +64 -61
- package/dist/utils/liquidDynamicContent.js +15 -0
- package/package.json +10 -6
|
@@ -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;
|
|
@@ -134,7 +134,10 @@ ue-orderable.orderable-disabled .droppable-icon {
|
|
|
134
134
|
border-top: 2px solid var(--guido-color-primary-500, #0A2ECC);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
/* Namespaced: Stripo ships a global \`.drag-handle { position: absolute }\` for its
|
|
138
|
+
floating popups, which knocked this handle out of flow (SD-151734). */
|
|
139
|
+
.guido-drag-handle {
|
|
140
|
+
cursor: move;
|
|
138
141
|
user-select: none;
|
|
139
142
|
display: flex;
|
|
140
143
|
align-items: center;
|
|
@@ -144,13 +147,13 @@ ue-orderable.orderable-disabled .droppable-icon {
|
|
|
144
147
|
flex-shrink: 0;
|
|
145
148
|
}
|
|
146
149
|
|
|
147
|
-
.drag-handle .drag-handle-btn .button {
|
|
150
|
+
.guido-drag-handle .guido-drag-handle-btn .button {
|
|
148
151
|
padding: 0;
|
|
149
152
|
min-width: auto;
|
|
150
153
|
cursor: move;
|
|
151
154
|
}
|
|
152
155
|
|
|
153
|
-
.drag-handle .drag-handle-btn .button .icon-button {
|
|
156
|
+
.guido-drag-handle .guido-drag-handle-btn .button .icon-button {
|
|
154
157
|
color: var(--guido-color-gray-600);
|
|
155
158
|
}
|
|
156
159
|
|
|
@@ -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
|
-
|
|
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();
|
|
15
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,21 +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
62
|
filterSnapshot: null,
|
|
60
|
-
syncedConfigFingerprint: null
|
|
63
|
+
syncedConfigFingerprint: null,
|
|
64
|
+
legacyConversionLoading: !1
|
|
61
65
|
};
|
|
62
66
|
}
|
|
63
|
-
const
|
|
67
|
+
const E = () => ({
|
|
64
68
|
recommendationCampaignUrls: {},
|
|
65
69
|
activePredictiveAlgorithms: [],
|
|
66
70
|
languages: {},
|
|
@@ -72,8 +76,8 @@ const z = () => ({
|
|
|
72
76
|
blockStates: {},
|
|
73
77
|
currentRecommendationId: null,
|
|
74
78
|
configVersion: 0
|
|
75
|
-
}),
|
|
76
|
-
state: () =>
|
|
79
|
+
}), et = L("guidoRecommendationExtension", {
|
|
80
|
+
state: () => E(),
|
|
77
81
|
getters: {
|
|
78
82
|
// ====================================================================
|
|
79
83
|
// Proxy Getters — Backward Compatible Access to Current Block State
|
|
@@ -83,7 +87,7 @@ const z = () => ({
|
|
|
83
87
|
* This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
|
|
84
88
|
*/
|
|
85
89
|
recommendationConfigs(t) {
|
|
86
|
-
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();
|
|
87
91
|
},
|
|
88
92
|
/**
|
|
89
93
|
* Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
|
|
@@ -103,6 +107,15 @@ const z = () => ({
|
|
|
103
107
|
removeStrategyModalStatus(t) {
|
|
104
108
|
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].removeStrategyModalStatus : !1;
|
|
105
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
|
+
},
|
|
106
119
|
assignedStrategy(t) {
|
|
107
120
|
const { strategyId: e } = this.recommendationConfigs;
|
|
108
121
|
return e ? t.strategies.find((r) => String(r.strategy_id) === e) ?? null : null;
|
|
@@ -138,8 +151,8 @@ const z = () => ({
|
|
|
138
151
|
return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
|
|
139
152
|
},
|
|
140
153
|
getActivePredictiveAlgorithms: (t) => {
|
|
141
|
-
const e =
|
|
142
|
-
return t.activePredictiveAlgorithms.filter((n) => !
|
|
154
|
+
const e = R(), r = [];
|
|
155
|
+
return t.activePredictiveAlgorithms.filter((n) => !M.includes(n)).forEach((n) => {
|
|
143
156
|
r.push(...e.filter((s) => s.id === n));
|
|
144
157
|
}), r.map((n) => ({
|
|
145
158
|
text: n.name,
|
|
@@ -157,7 +170,7 @@ const z = () => ({
|
|
|
157
170
|
getFilterList() {
|
|
158
171
|
return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
|
|
159
172
|
let e;
|
|
160
|
-
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, {
|
|
161
174
|
text: t.displayName,
|
|
162
175
|
value: e,
|
|
163
176
|
type: t.attributeType
|
|
@@ -179,7 +192,7 @@ const z = () => ({
|
|
|
179
192
|
setCurrentBlock(t) {
|
|
180
193
|
this.blockStates[t] || (this.blockStates = {
|
|
181
194
|
...this.blockStates,
|
|
182
|
-
[t]:
|
|
195
|
+
[t]: w()
|
|
183
196
|
}), this.currentRecommendationId = t;
|
|
184
197
|
},
|
|
185
198
|
/**
|
|
@@ -247,7 +260,7 @@ const z = () => ({
|
|
|
247
260
|
decimalCount: String(e.currencyDecimalCount),
|
|
248
261
|
decimalSeparator: r(e.currencyDecimalSeparator, ","),
|
|
249
262
|
thousandSeparator: r(e.currencyThousandSeparator, ".")
|
|
250
|
-
}, s = !this.blockStates[t], i = s ?
|
|
263
|
+
}, s = !this.blockStates[t], i = s ? w() : this.blockStates[t];
|
|
251
264
|
i.recommendationConfigs = {
|
|
252
265
|
...i.recommendationConfigs,
|
|
253
266
|
strategy: e.strategy,
|
|
@@ -286,7 +299,7 @@ const z = () => ({
|
|
|
286
299
|
* Creates a filter with the first available attribute and operator pre-selected.
|
|
287
300
|
*/
|
|
288
301
|
createDefaultFilter(t, e) {
|
|
289
|
-
const [r] = this.getFilterList, [n] =
|
|
302
|
+
const [r] = this.getFilterList, [n] = F(r == null ? void 0 : r.type);
|
|
290
303
|
return {
|
|
291
304
|
type: "standardFilter",
|
|
292
305
|
attribute: (r == null ? void 0 : r.value) ?? "",
|
|
@@ -339,6 +352,12 @@ const z = () => ({
|
|
|
339
352
|
closeAssignStrategyDrawer() {
|
|
340
353
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !1);
|
|
341
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
|
+
},
|
|
342
361
|
openRemoveStrategyModal() {
|
|
343
362
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !0);
|
|
344
363
|
},
|
|
@@ -353,7 +372,7 @@ const z = () => ({
|
|
|
353
372
|
S = (async () => {
|
|
354
373
|
this.strategiesLoading = !0;
|
|
355
374
|
try {
|
|
356
|
-
this.strategies = await
|
|
375
|
+
this.strategies = await m.fetchRecommendationStrategies();
|
|
357
376
|
} finally {
|
|
358
377
|
this.strategiesLoading = !1;
|
|
359
378
|
}
|
|
@@ -368,7 +387,7 @@ const z = () => ({
|
|
|
368
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;
|
|
369
388
|
if (s)
|
|
370
389
|
return s;
|
|
371
|
-
const { full_path: i = "" } = await
|
|
390
|
+
const { full_path: i = "" } = await m.generateStrategyEndpoint(t, e) ?? {};
|
|
372
391
|
return n && i && (this.strategyUrlTemplates = {
|
|
373
392
|
...this.strategyUrlTemplates,
|
|
374
393
|
[n]: i
|
|
@@ -380,8 +399,44 @@ const z = () => ({
|
|
|
380
399
|
...t.size !== void 0 ? { size: String(t.size) } : {}
|
|
381
400
|
});
|
|
382
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
|
+
},
|
|
383
434
|
removeStrategy() {
|
|
384
|
-
this.patchCurrentBlockConfig({
|
|
435
|
+
this.patchCurrentBlockConfig({
|
|
436
|
+
strategyId: "",
|
|
437
|
+
size: N.size,
|
|
438
|
+
nodeConfigVersion: y
|
|
439
|
+
});
|
|
385
440
|
},
|
|
386
441
|
// ====================================================================
|
|
387
442
|
// Shared Data Fetching (fetched once, used by all blocks)
|
|
@@ -397,7 +452,7 @@ const z = () => ({
|
|
|
397
452
|
activePredictiveAlgorithms: t,
|
|
398
453
|
languages: e,
|
|
399
454
|
currencies: r
|
|
400
|
-
} = await
|
|
455
|
+
} = await m.fetchRecommendationCreateData();
|
|
401
456
|
if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
|
|
402
457
|
const n = this.blockStates[this.currentRecommendationId];
|
|
403
458
|
n.filterStatus = !!n.recommendationConfigs.filters.length;
|
|
@@ -418,7 +473,7 @@ const z = () => ({
|
|
|
418
473
|
return;
|
|
419
474
|
}
|
|
420
475
|
g = (async () => {
|
|
421
|
-
const t = await
|
|
476
|
+
const t = await m.fetchRecommendationFilters();
|
|
422
477
|
this.filterList = t;
|
|
423
478
|
})();
|
|
424
479
|
try {
|
|
@@ -453,7 +508,7 @@ const z = () => ({
|
|
|
453
508
|
const n = [...e.recommendationConfigs.filters];
|
|
454
509
|
n[r] = {
|
|
455
510
|
...t,
|
|
456
|
-
isValid:
|
|
511
|
+
isValid: A(t)
|
|
457
512
|
}, e.recommendationConfigs.filters = n;
|
|
458
513
|
}
|
|
459
514
|
},
|
|
@@ -491,7 +546,7 @@ const z = () => ({
|
|
|
491
546
|
}), e.recommendationConfigs.filters = r;
|
|
492
547
|
},
|
|
493
548
|
generateFilterQuery() {
|
|
494
|
-
return
|
|
549
|
+
return v(this.recommendationConfigs.filters);
|
|
495
550
|
},
|
|
496
551
|
/**
|
|
497
552
|
* Validation-only check invoked at save-CTA time. Defined as an action
|
|
@@ -499,7 +554,7 @@ const z = () => ({
|
|
|
499
554
|
* every block's recommendationConfigs across user edits.
|
|
500
555
|
*/
|
|
501
556
|
hasInvalidBlock() {
|
|
502
|
-
return Object.values(this.blockStates).some((t) => !
|
|
557
|
+
return Object.values(this.blockStates).some((t) => !O(t.recommendationConfigs, this));
|
|
503
558
|
},
|
|
504
559
|
// ====================================================================
|
|
505
560
|
// Per-Block Product Fetching
|
|
@@ -520,12 +575,12 @@ const z = () => ({
|
|
|
520
575
|
},
|
|
521
576
|
async _doFetchProducts() {
|
|
522
577
|
var d;
|
|
523
|
-
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();
|
|
524
579
|
if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
|
|
525
580
|
await this._doFetchStrategyProducts(t);
|
|
526
581
|
return;
|
|
527
582
|
}
|
|
528
|
-
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 = {
|
|
529
584
|
locale: r.language,
|
|
530
585
|
currency: r.currencySettings.value,
|
|
531
586
|
partnerName: n.partnerName,
|
|
@@ -533,18 +588,27 @@ const z = () => ({
|
|
|
533
588
|
details: !0,
|
|
534
589
|
campaignId: n.variationId
|
|
535
590
|
};
|
|
536
|
-
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(
|
|
537
592
|
a,
|
|
538
|
-
|
|
593
|
+
B(n.partnerName, r.strategy)
|
|
539
594
|
);
|
|
540
595
|
let l;
|
|
541
596
|
try {
|
|
542
|
-
l = await
|
|
597
|
+
l = await m.fetchRecommendationProducts(o, a);
|
|
543
598
|
} catch {
|
|
544
599
|
l = [];
|
|
545
600
|
}
|
|
546
601
|
this._setBlockProducts(t, l, c);
|
|
547
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
|
+
},
|
|
548
612
|
async _doFetchStrategyProducts(t) {
|
|
549
613
|
const e = (p.get(t) ?? 0) + 1;
|
|
550
614
|
p.set(t, e);
|
|
@@ -557,8 +621,8 @@ const z = () => ({
|
|
|
557
621
|
);
|
|
558
622
|
if (i) {
|
|
559
623
|
s = parseInt(String(i.size ?? "")) || s;
|
|
560
|
-
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),
|
|
561
|
-
|
|
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));
|
|
562
626
|
}
|
|
563
627
|
} catch {
|
|
564
628
|
n = [];
|
|
@@ -568,14 +632,14 @@ const z = () => ({
|
|
|
568
632
|
_setBlockProducts(t, e, r) {
|
|
569
633
|
if (!this.blockStates[t])
|
|
570
634
|
return;
|
|
571
|
-
const n = e.length > 0 ? e :
|
|
635
|
+
const n = e.length > 0 ? e : C(r);
|
|
572
636
|
this.blockStates[t].recommendationProducts = [
|
|
573
637
|
...n.slice(0, r),
|
|
574
|
-
...
|
|
638
|
+
...C(Math.max(0, r - n.length))
|
|
575
639
|
];
|
|
576
640
|
}
|
|
577
641
|
}
|
|
578
642
|
});
|
|
579
643
|
export {
|
|
580
|
-
|
|
644
|
+
et as useRecommendationExtensionStore
|
|
581
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
|
};
|