@useinsider/guido 3.19.0-beta.c8d2be8 → 3.19.0-beta.cd25cc8
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/@types/config/schemas.js +104 -91
- package/dist/components/Guido.vue.js +6 -6
- package/dist/components/Guido.vue2.js +96 -85
- package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
- package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
- package/dist/components/organisms/header/EditorActions.vue.js +4 -4
- package/dist/components/organisms/header/EditorActions.vue2.js +23 -25
- package/dist/components/wrappers/WpModal.vue.js +1 -1
- package/dist/components/wrappers/WpModal.vue2.js +4 -3
- package/dist/composables/useActionsApi.js +52 -47
- package/dist/composables/useAuthError.js +52 -0
- package/dist/composables/useAutoSave.js +11 -11
- package/dist/composables/useCodeEditorApi.js +23 -9
- package/dist/composables/useCortexBlueprintBridge.js +122 -54
- package/dist/composables/useEmailTemplateApplier.js +111 -50
- package/dist/composables/useHttp.js +48 -49
- package/dist/composables/useLegacyStrategyConversion.js +23 -19
- package/dist/composables/useStripo.js +24 -20
- package/dist/composables/useToaster.js +17 -15
- package/dist/composables/useTranslations.js +3 -2
- package/dist/composables/useVersionHistoryApi.js +33 -24
- package/dist/composables/validators/useLiquidValidator.js +15 -15
- package/dist/config/migrator/index.js +14 -13
- package/dist/config/migrator/itemsBlockMigrator.js +236 -248
- package/dist/config/migrator/recommendationMigrator.js +28 -21
- package/dist/config/migrator/recommendationPartnerMigrator.js +56 -0
- package/dist/enums/extensions/recommendationBlock.js +30 -29
- package/dist/extensions/Blocks/Items/constants/cardLayout.js +20 -0
- package/dist/extensions/Blocks/Items/controls/name/trimming.js +18 -17
- package/dist/extensions/Blocks/Items/controls/settingsControl.js +114 -105
- package/dist/extensions/Blocks/Items/enums/productEnums.js +14 -9
- package/dist/extensions/Blocks/Items/layouts/horizontal.html.js +11 -9
- package/dist/extensions/Blocks/Items/template.js +219 -204
- package/dist/extensions/Blocks/Recommendation/block.js +21 -18
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +117 -93
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +72 -49
- package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +209 -203
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +130 -96
- package/dist/extensions/Blocks/Recommendation/utils/blockUrlConfig.js +25 -0
- package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +26 -21
- package/dist/extensions/Blocks/Recommendation/utils/partnerScope.js +25 -0
- package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +40 -17
- package/dist/guido.css +1 -1
- package/dist/src/@types/config/schemas.d.ts +16 -0
- package/dist/src/components/organisms/base/AuthErrorModal.vue.d.ts +2 -0
- package/dist/src/components/wrappers/WpModal.vue.d.ts +5 -1
- package/dist/src/composables/useAuthError.d.ts +12 -0
- package/dist/src/composables/useConfig.d.ts +2 -0
- package/dist/src/composables/useCortexBlueprintBridge.d.ts +2 -3
- package/dist/src/composables/useEmailTemplateApplier.d.ts +18 -5
- package/dist/src/composables/useGuidoActions.d.ts +2 -0
- package/dist/src/composables/useHttp.d.ts +2 -0
- package/dist/src/config/migrator/index.d.ts +2 -1
- package/dist/src/config/migrator/recommendationPartnerMigrator.d.ts +19 -0
- package/dist/src/enums/extensions/recommendationBlock.d.ts +1 -1
- package/dist/src/extensions/Blocks/Items/constants/cardLayout.d.ts +44 -0
- package/dist/src/extensions/Blocks/Items/enums/productEnums.d.ts +3 -0
- package/dist/src/extensions/Blocks/Items/template.d.ts +19 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +2 -0
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +16 -2
- package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +6 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/blockUrlConfig.d.ts +4 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/nodeConfigWriter.d.ts +3 -1
- package/dist/src/extensions/Blocks/Recommendation/utils/partnerScope.d.ts +33 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +7 -0
- package/dist/src/mock/cortexChatStore.d.ts +12 -0
- package/dist/src/stores/config.d.ts +20 -0
- package/dist/src/stores/guido-email-editor.d.ts +20 -10
- package/dist/src/stores/onboarding.d.ts +4 -0
- package/dist/src/stores/recommendation.d.ts +5 -0
- package/dist/src/utils/dateUtil.d.ts +10 -0
- package/dist/src/utils/genericUtil.d.ts +3 -0
- package/dist/src/utils/stripoEditorApi.d.ts +4 -0
- package/dist/static/styles/components/recommendation-strategy.css.js +9 -0
- package/dist/static/styles/components/version-history.css.js +2 -6
- package/dist/stores/guido-email-editor.js +3 -1
- package/dist/stores/onboarding.js +4 -0
- package/dist/stores/unsubscribe.js +3 -3
- package/dist/utils/pairProductVariables.js +71 -71
- package/dist/utils/stripoEditorApi.js +11 -0
- package/dist/utils/templatePreparation.js +61 -85
- package/package.json +2 -1
|
@@ -1,27 +1,31 @@
|
|
|
1
|
-
import { useToaster as
|
|
2
|
-
import { useTranslations as
|
|
3
|
-
import { getRecommendationFeedSourceMaps as
|
|
4
|
-
import { ToasterTypeOptions as
|
|
5
|
-
import { useRecommendationApi as
|
|
6
|
-
import { useConfigStore as
|
|
7
|
-
import { defineStore as
|
|
1
|
+
import { useToaster as U } from "../../../../composables/useToaster.js";
|
|
2
|
+
import { useTranslations as M } from "../../../../composables/useTranslations.js";
|
|
3
|
+
import { getRecommendationFeedSourceMaps as w, strategyEditPath as N, strategyCreatePath as B, getOperatorOptions as z, PriceAttributes as E } from "../../../../enums/extensions/recommendationBlock.js";
|
|
4
|
+
import { ToasterTypeOptions as O } from "../../../../enums/toaster.js";
|
|
5
|
+
import { useRecommendationApi as A } from "../../../../services/recommendationApi.js";
|
|
6
|
+
import { useConfigStore as R } from "../../../../stores/config.js";
|
|
7
|
+
import { defineStore as x } from "pinia";
|
|
8
8
|
import "../constants/selectors.js";
|
|
9
|
-
import { DEFAULT_MOBILE_CARDS_IN_ROW as
|
|
10
|
-
import { CURRENT_CONFIG_VERSION as C, DEFAULT_NODE_CONFIG as
|
|
11
|
-
import { getDefaultProducts as
|
|
12
|
-
import { generateCompleteFilterQuery as
|
|
13
|
-
import { isLegacyStrategyConfig as
|
|
14
|
-
import { getPartnerRecommendationParams as
|
|
15
|
-
import { sanitizeProductIds as
|
|
16
|
-
import { isFilterValid as
|
|
17
|
-
import { getInvalidFields as
|
|
18
|
-
const
|
|
19
|
-
let S = null,
|
|
20
|
-
const
|
|
9
|
+
import { DEFAULT_MOBILE_CARDS_IN_ROW as T, DEFAULT_CARDS_IN_ROW as V } from "../constants/layout.js";
|
|
10
|
+
import { CURRENT_CONFIG_VERSION as C, DEFAULT_NODE_CONFIG as j, EXCLUDED_ALGORITHM_IDS as $ } from "../constants/defaultConfig.js";
|
|
11
|
+
import { getDefaultProducts as P } from "../templates/utils.js";
|
|
12
|
+
import { generateCompleteFilterQuery as G } from "../utils/filterUtil.js";
|
|
13
|
+
import { isLegacyStrategyConfig as q } from "../utils/legacyStrategyMigration.js";
|
|
14
|
+
import { getPartnerRecommendationParams as K } from "../utils/partnerCustomizations.js";
|
|
15
|
+
import { sanitizeProductIds as H } from "../utils/productIds.js";
|
|
16
|
+
import { isFilterValid as J } from "../validation/filterSchema.js";
|
|
17
|
+
import { getInvalidFields as Q, isConfigValid as W } from "../validation/requiredFields.js";
|
|
18
|
+
const u = A();
|
|
19
|
+
let S = null, y = null, p = null, I = "", k = null, b = 0;
|
|
20
|
+
const m = /* @__PURE__ */ new Map(), D = /* @__PURE__ */ new Map();
|
|
21
|
+
function X(t) {
|
|
22
|
+
const e = D.get(t);
|
|
23
|
+
return e && e.token === m.get(t) ? e.outcome : !1;
|
|
24
|
+
}
|
|
21
25
|
let l = null;
|
|
22
|
-
function
|
|
26
|
+
function L() {
|
|
23
27
|
return {
|
|
24
|
-
cardsInRow:
|
|
28
|
+
cardsInRow: V,
|
|
25
29
|
currencySettings: {
|
|
26
30
|
name: "USD",
|
|
27
31
|
value: "USD",
|
|
@@ -35,7 +39,7 @@ function _() {
|
|
|
35
39
|
productIds: [],
|
|
36
40
|
id: 1,
|
|
37
41
|
language: "en_US",
|
|
38
|
-
mobileCardsInRow:
|
|
42
|
+
mobileCardsInRow: T,
|
|
39
43
|
mobileLayoutEnabled: !1,
|
|
40
44
|
orientation: "grid",
|
|
41
45
|
recommendedProducts: [],
|
|
@@ -45,7 +49,7 @@ function _() {
|
|
|
45
49
|
// that default is what reached buildCampaignUrl and baked a most-popular feed URL
|
|
46
50
|
// for a block the user never configured (SD-149916). Legacy blocks still get their real
|
|
47
51
|
// algorithm from the node-config sync or the save-time seed.
|
|
48
|
-
strategy:
|
|
52
|
+
strategy: R().isFeatureEnabled("reusableRecommendationStrategy") ? "" : "mostPopular",
|
|
49
53
|
strategyId: "",
|
|
50
54
|
nodeConfigVersion: C,
|
|
51
55
|
textTrimming: !0,
|
|
@@ -56,9 +60,9 @@ function _() {
|
|
|
56
60
|
priceHideIfSameAsDiscounted: !1
|
|
57
61
|
};
|
|
58
62
|
}
|
|
59
|
-
function
|
|
63
|
+
function _() {
|
|
60
64
|
return {
|
|
61
|
-
recommendationConfigs:
|
|
65
|
+
recommendationConfigs: L(),
|
|
62
66
|
recommendationProducts: [],
|
|
63
67
|
filterStatus: !1,
|
|
64
68
|
filterSelectionDrawerStatus: !1,
|
|
@@ -72,7 +76,7 @@ function G() {
|
|
|
72
76
|
legacyConversionLoading: !1
|
|
73
77
|
};
|
|
74
78
|
}
|
|
75
|
-
const
|
|
79
|
+
const Y = () => ({
|
|
76
80
|
recommendationCampaignUrls: {},
|
|
77
81
|
activePredictiveAlgorithms: [],
|
|
78
82
|
languages: {},
|
|
@@ -87,8 +91,8 @@ const Q = () => ({
|
|
|
87
91
|
currentRecommendationId: null,
|
|
88
92
|
strategyPanelOpen: !1,
|
|
89
93
|
configVersion: 0
|
|
90
|
-
}),
|
|
91
|
-
state: () =>
|
|
94
|
+
}), St = x("guidoRecommendationExtension", {
|
|
95
|
+
state: () => Y(),
|
|
92
96
|
getters: {
|
|
93
97
|
// ====================================================================
|
|
94
98
|
// Proxy Getters — Backward Compatible Access to Current Block State
|
|
@@ -98,7 +102,7 @@ const Q = () => ({
|
|
|
98
102
|
* This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
|
|
99
103
|
*/
|
|
100
104
|
recommendationConfigs(t) {
|
|
101
|
-
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs :
|
|
105
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : L();
|
|
102
106
|
},
|
|
103
107
|
/**
|
|
104
108
|
* Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
|
|
@@ -119,7 +123,7 @@ const Q = () => ({
|
|
|
119
123
|
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].removeStrategyModalStatus : !1;
|
|
120
124
|
},
|
|
121
125
|
isLegacyStrategyBlock() {
|
|
122
|
-
return
|
|
126
|
+
return R().isFeatureEnabled("reusableRecommendationStrategy") && q(this.recommendationConfigs);
|
|
123
127
|
},
|
|
124
128
|
legacyConversionLoading(t) {
|
|
125
129
|
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].legacyConversionLoading ?? !1 : !1;
|
|
@@ -162,8 +166,8 @@ const Q = () => ({
|
|
|
162
166
|
return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
|
|
163
167
|
},
|
|
164
168
|
getActivePredictiveAlgorithms: (t) => {
|
|
165
|
-
const e =
|
|
166
|
-
return t.activePredictiveAlgorithms.filter((n) =>
|
|
169
|
+
const e = w(), r = [];
|
|
170
|
+
return t.activePredictiveAlgorithms.filter((n) => !$.includes(n)).forEach((n) => {
|
|
167
171
|
r.push(...e.filter((s) => s.id === n));
|
|
168
172
|
}), r.map((n) => ({
|
|
169
173
|
text: n.name,
|
|
@@ -181,7 +185,7 @@ const Q = () => ({
|
|
|
181
185
|
getFilterList() {
|
|
182
186
|
return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
|
|
183
187
|
let e;
|
|
184
|
-
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` :
|
|
188
|
+
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : E.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
|
|
185
189
|
text: t.displayName,
|
|
186
190
|
value: e,
|
|
187
191
|
type: t.attributeType
|
|
@@ -203,7 +207,7 @@ const Q = () => ({
|
|
|
203
207
|
setCurrentBlock(t) {
|
|
204
208
|
this.blockStates[t] || (this.blockStates = {
|
|
205
209
|
...this.blockStates,
|
|
206
|
-
[t]:
|
|
210
|
+
[t]: _()
|
|
207
211
|
}), this.currentRecommendationId = t;
|
|
208
212
|
},
|
|
209
213
|
/**
|
|
@@ -234,7 +238,7 @@ const Q = () => ({
|
|
|
234
238
|
const r = this.blockStates[t];
|
|
235
239
|
if (r) {
|
|
236
240
|
const o = structuredClone(r);
|
|
237
|
-
o.recommendationConfigs.id = e, o.recommendationConfigs.strategyId &&
|
|
241
|
+
o.recommendationConfigs.id = e, o.recommendationConfigs.strategyId && R().isFeatureEnabled("reusableRecommendationStrategy") && (o.isInitialized = !1, o.syncedConfigFingerprint = null), this.blockStates = {
|
|
238
242
|
...this.blockStates,
|
|
239
243
|
[e]: o
|
|
240
244
|
};
|
|
@@ -275,7 +279,7 @@ const Q = () => ({
|
|
|
275
279
|
decimalCount: String(e.currencyDecimalCount),
|
|
276
280
|
decimalSeparator: r(e.currencyDecimalSeparator, ","),
|
|
277
281
|
thousandSeparator: r(e.currencyThousandSeparator, ".")
|
|
278
|
-
}, s = !this.blockStates[t], i = s ?
|
|
282
|
+
}, s = !this.blockStates[t], i = s ? _() : this.blockStates[t];
|
|
279
283
|
i.recommendationConfigs = {
|
|
280
284
|
...i.recommendationConfigs,
|
|
281
285
|
strategy: e.strategy,
|
|
@@ -314,7 +318,7 @@ const Q = () => ({
|
|
|
314
318
|
* Creates a filter with the first available attribute and operator pre-selected.
|
|
315
319
|
*/
|
|
316
320
|
createDefaultFilter(t, e) {
|
|
317
|
-
const [r] = this.getFilterList, [n] =
|
|
321
|
+
const [r] = this.getFilterList, [n] = z(r == null ? void 0 : r.type);
|
|
318
322
|
return {
|
|
319
323
|
type: "standardFilter",
|
|
320
324
|
attribute: (r == null ? void 0 : r.value) ?? "",
|
|
@@ -380,9 +384,9 @@ const Q = () => ({
|
|
|
380
384
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !1);
|
|
381
385
|
},
|
|
382
386
|
async fetchStrategies() {
|
|
383
|
-
for (;
|
|
387
|
+
for (; k; )
|
|
384
388
|
try {
|
|
385
|
-
await
|
|
389
|
+
await k;
|
|
386
390
|
} catch {
|
|
387
391
|
}
|
|
388
392
|
if (this.strategiesFetched)
|
|
@@ -390,7 +394,7 @@ const Q = () => ({
|
|
|
390
394
|
const t = b, e = (async () => {
|
|
391
395
|
this.strategiesLoading = !0;
|
|
392
396
|
try {
|
|
393
|
-
const r = await
|
|
397
|
+
const r = await u.fetchRecommendationStrategies();
|
|
394
398
|
if (t !== b)
|
|
395
399
|
return;
|
|
396
400
|
this.strategies = r, this.strategiesFetched = !0;
|
|
@@ -398,11 +402,11 @@ const Q = () => ({
|
|
|
398
402
|
this.strategiesLoading = !1, t === b && (this.strategiesSettled = !0);
|
|
399
403
|
}
|
|
400
404
|
})();
|
|
401
|
-
|
|
405
|
+
k = e;
|
|
402
406
|
try {
|
|
403
407
|
await e;
|
|
404
408
|
} finally {
|
|
405
|
-
|
|
409
|
+
k = null;
|
|
406
410
|
}
|
|
407
411
|
},
|
|
408
412
|
/**
|
|
@@ -434,9 +438,9 @@ const Q = () => ({
|
|
|
434
438
|
_armStrategyPageReturn(t) {
|
|
435
439
|
const e = window.open(t, "_blank");
|
|
436
440
|
if (!e)
|
|
437
|
-
return
|
|
438
|
-
type:
|
|
439
|
-
message:
|
|
441
|
+
return U().showToaster({
|
|
442
|
+
type: O.Error,
|
|
443
|
+
message: M()("discovery-strategy.error-description")
|
|
440
444
|
}), !1;
|
|
441
445
|
e.opener = null, l == null || l();
|
|
442
446
|
let r = !1;
|
|
@@ -471,20 +475,20 @@ const Q = () => ({
|
|
|
471
475
|
* new strategy is offered; the user picks it themselves.
|
|
472
476
|
*/
|
|
473
477
|
openStrategyCreation() {
|
|
474
|
-
return this._armStrategyPageReturn(
|
|
478
|
+
return this._armStrategyPageReturn(B());
|
|
475
479
|
},
|
|
476
480
|
/**
|
|
477
481
|
* Opens the strategy's edit page. Every return refreshes the list so the block reflects the
|
|
478
482
|
* edited configuration.
|
|
479
483
|
*/
|
|
480
484
|
openStrategyEdit(t) {
|
|
481
|
-
return this._armStrategyPageReturn(
|
|
485
|
+
return this._armStrategyPageReturn(N(t));
|
|
482
486
|
},
|
|
483
487
|
async resolveStrategyUrlTemplate(t, e) {
|
|
484
488
|
const r = typeof t.updated_at == "string" ? t.updated_at : "", n = r ? `${t.strategy_id}:${r}:${e}` : "", s = n ? this.strategyUrlTemplates[n] : void 0;
|
|
485
489
|
if (s)
|
|
486
490
|
return s;
|
|
487
|
-
const { full_path: i = "" } = await
|
|
491
|
+
const { full_path: i = "" } = await u.generateStrategyEndpoint(t, e) ?? {};
|
|
488
492
|
return n && i && (this.strategyUrlTemplates = {
|
|
489
493
|
...this.strategyUrlTemplates,
|
|
490
494
|
[n]: i
|
|
@@ -502,7 +506,8 @@ const Q = () => ({
|
|
|
502
506
|
throw new Error("[Guido] convertLegacyStrategy called without an active block");
|
|
503
507
|
this.blockStates[r].legacyConversionLoading = !0;
|
|
504
508
|
try {
|
|
505
|
-
const n = await
|
|
509
|
+
const n = await u.migrateLegacyStrategy(t, e);
|
|
510
|
+
this.invalidateStrategies();
|
|
506
511
|
try {
|
|
507
512
|
await this.fetchStrategies();
|
|
508
513
|
} catch (o) {
|
|
@@ -532,7 +537,7 @@ const Q = () => ({
|
|
|
532
537
|
this.patchCurrentBlockConfig({
|
|
533
538
|
strategyId: "",
|
|
534
539
|
strategy: "",
|
|
535
|
-
size:
|
|
540
|
+
size: j.size,
|
|
536
541
|
nodeConfigVersion: C
|
|
537
542
|
});
|
|
538
543
|
},
|
|
@@ -550,7 +555,7 @@ const Q = () => ({
|
|
|
550
555
|
activePredictiveAlgorithms: t,
|
|
551
556
|
languages: e,
|
|
552
557
|
currencies: r
|
|
553
|
-
} = await
|
|
558
|
+
} = await u.fetchRecommendationCreateData();
|
|
554
559
|
if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
|
|
555
560
|
const n = this.blockStates[this.currentRecommendationId];
|
|
556
561
|
n.filterStatus = !!n.recommendationConfigs.filters.length;
|
|
@@ -566,18 +571,18 @@ const Q = () => ({
|
|
|
566
571
|
},
|
|
567
572
|
async fetchRecommendationFilters() {
|
|
568
573
|
if (!Object.keys(this.filterList).length) {
|
|
569
|
-
if (
|
|
570
|
-
await
|
|
574
|
+
if (y) {
|
|
575
|
+
await y;
|
|
571
576
|
return;
|
|
572
577
|
}
|
|
573
|
-
|
|
574
|
-
const t = await
|
|
578
|
+
y = (async () => {
|
|
579
|
+
const t = await u.fetchRecommendationFilters();
|
|
575
580
|
this.filterList = t;
|
|
576
581
|
})();
|
|
577
582
|
try {
|
|
578
|
-
await
|
|
583
|
+
await y;
|
|
579
584
|
} finally {
|
|
580
|
-
|
|
585
|
+
y = null;
|
|
581
586
|
}
|
|
582
587
|
}
|
|
583
588
|
},
|
|
@@ -606,7 +611,7 @@ const Q = () => ({
|
|
|
606
611
|
const n = [...e.recommendationConfigs.filters];
|
|
607
612
|
n[r] = {
|
|
608
613
|
...t,
|
|
609
|
-
isValid:
|
|
614
|
+
isValid: J(t)
|
|
610
615
|
}, e.recommendationConfigs.filters = n;
|
|
611
616
|
}
|
|
612
617
|
},
|
|
@@ -620,7 +625,7 @@ const Q = () => ({
|
|
|
620
625
|
let i = 1;
|
|
621
626
|
n = n.map((o) => o.filterGroup === t.filterGroup ? { ...o, filterNumber: i++ } : o);
|
|
622
627
|
} else {
|
|
623
|
-
const i = [...new Set(n.map((a) => a.filterGroup))].sort((a,
|
|
628
|
+
const i = [...new Set(n.map((a) => a.filterGroup))].sort((a, f) => a - f), o = new Map(i.map((a, f) => [a, f + 1]));
|
|
624
629
|
n = n.map((a) => ({
|
|
625
630
|
...a,
|
|
626
631
|
filterGroup: o.get(a.filterGroup) ?? a.filterGroup
|
|
@@ -644,7 +649,7 @@ const Q = () => ({
|
|
|
644
649
|
}), e.recommendationConfigs.filters = r;
|
|
645
650
|
},
|
|
646
651
|
generateFilterQuery() {
|
|
647
|
-
return
|
|
652
|
+
return G(this.recommendationConfigs.filters);
|
|
648
653
|
},
|
|
649
654
|
/**
|
|
650
655
|
* Validation-only check invoked at save-CTA time. Defined as an action
|
|
@@ -652,14 +657,14 @@ const Q = () => ({
|
|
|
652
657
|
* every block's recommendationConfigs across user edits.
|
|
653
658
|
*/
|
|
654
659
|
hasInvalidBlock() {
|
|
655
|
-
return Object.values(this.blockStates).some((t) => !
|
|
660
|
+
return Object.values(this.blockStates).some((t) => !W(t.recommendationConfigs, this));
|
|
656
661
|
},
|
|
657
662
|
/**
|
|
658
663
|
* Which required fields are missing across the design's blocks, so the save
|
|
659
664
|
* toaster can name the cause instead of always showing the generic message.
|
|
660
665
|
*/
|
|
661
666
|
invalidBlockFields() {
|
|
662
|
-
return Object.values(this.blockStates).flatMap((t) =>
|
|
667
|
+
return Object.values(this.blockStates).flatMap((t) => Q(t.recommendationConfigs, this));
|
|
663
668
|
},
|
|
664
669
|
// ====================================================================
|
|
665
670
|
// Per-Block Product Fetching
|
|
@@ -672,32 +677,32 @@ const Q = () => ({
|
|
|
672
677
|
this.configVersion,
|
|
673
678
|
b
|
|
674
679
|
].join(":");
|
|
675
|
-
if (
|
|
676
|
-
await
|
|
680
|
+
if (p && I === t) {
|
|
681
|
+
await p;
|
|
677
682
|
return;
|
|
678
683
|
}
|
|
679
|
-
I = t,
|
|
684
|
+
I = t, p = this._doFetchProducts();
|
|
680
685
|
try {
|
|
681
|
-
await
|
|
686
|
+
await p;
|
|
682
687
|
} finally {
|
|
683
|
-
I === t && (
|
|
688
|
+
I === t && (p = null, I = "");
|
|
684
689
|
}
|
|
685
690
|
},
|
|
686
691
|
async _doFetchProducts() {
|
|
687
692
|
var h;
|
|
688
|
-
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n =
|
|
693
|
+
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = R();
|
|
689
694
|
if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
|
|
690
695
|
await this._doFetchStrategyProducts(t);
|
|
691
696
|
return;
|
|
692
697
|
}
|
|
693
|
-
const s = (
|
|
694
|
-
|
|
698
|
+
const s = (m.get(t) ?? 0) + 1;
|
|
699
|
+
m.set(t, s);
|
|
695
700
|
const i = parseInt(r.size) || 6;
|
|
696
701
|
if (!r.strategy) {
|
|
697
702
|
this._setBlockProducts(t, [], i);
|
|
698
703
|
return;
|
|
699
704
|
}
|
|
700
|
-
const o = r.filters.filter((
|
|
705
|
+
const o = r.filters.filter((g) => g.isValid), a = G(o), f = ((h = w().find((g) => g.key === r.strategy)) == null ? void 0 : h.path) || "", c = {
|
|
701
706
|
locale: r.language,
|
|
702
707
|
currency: r.currencySettings.value,
|
|
703
708
|
partnerName: n.partnerName,
|
|
@@ -705,58 +710,87 @@ const Q = () => ({
|
|
|
705
710
|
details: !0,
|
|
706
711
|
campaignId: n.variationId
|
|
707
712
|
};
|
|
708
|
-
r.strategy === "manualMerchandising" ? c.productId =
|
|
713
|
+
r.strategy === "manualMerchandising" ? c.productId = H(r.productIds) : r.strategy === "similarViewed" && (c.productId = "{itemId}"), r.strategy === "userBased" && (c.userId = "{user_id}"), a && (c.filter = a), r.shuffleProducts && (c.shuffle = !0), Object.assign(
|
|
709
714
|
c,
|
|
710
|
-
|
|
715
|
+
K(n.partnerName, r.strategy)
|
|
711
716
|
);
|
|
712
|
-
let
|
|
717
|
+
let d;
|
|
713
718
|
try {
|
|
714
|
-
|
|
719
|
+
d = await u.fetchRecommendationProducts(f, c);
|
|
715
720
|
} catch {
|
|
716
|
-
|
|
721
|
+
d = [];
|
|
717
722
|
}
|
|
718
|
-
|
|
723
|
+
m.get(t) === s && this._setBlockProducts(t, d, i);
|
|
719
724
|
},
|
|
720
725
|
/**
|
|
721
726
|
* Block-scoped counterpart of `fetchRecommendationProducts`, which only ever serves the
|
|
722
727
|
* selected block. The legacy conversion must refresh the products of the block that
|
|
723
728
|
* started it even after the user selected another one.
|
|
729
|
+
* @returns whether real products arrived
|
|
724
730
|
*/
|
|
725
|
-
async fetchStrategyProductsForBlock(t) {
|
|
726
|
-
var
|
|
727
|
-
(
|
|
731
|
+
async fetchStrategyProductsForBlock(t, e = {}) {
|
|
732
|
+
var r;
|
|
733
|
+
return (r = this.blockStates[t]) != null && r.recommendationConfigs.strategyId ? this._doFetchStrategyProducts(t, e) : !1;
|
|
728
734
|
},
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
735
|
+
/**
|
|
736
|
+
* Reloads a block's products and adopts its strategy's current size, which may have
|
|
737
|
+
* moved since the block was assigned.
|
|
738
|
+
* @returns whether a fresh listing holds the strategy and its products arrived
|
|
739
|
+
*/
|
|
740
|
+
async refreshStrategyBlock(t) {
|
|
741
|
+
var s;
|
|
742
|
+
const e = (s = this.blockStates[t]) == null ? void 0 : s.recommendationConfigs.strategyId;
|
|
743
|
+
if (!e)
|
|
744
|
+
return !1;
|
|
745
|
+
try {
|
|
746
|
+
await this.fetchStrategies();
|
|
747
|
+
} catch {
|
|
748
|
+
return !1;
|
|
749
|
+
}
|
|
750
|
+
const r = this.strategiesFetched ? this.strategies.find((i) => String(i.strategy_id) === e) : void 0;
|
|
751
|
+
if (!r || !await this.fetchStrategyProductsForBlock(t, { keepOnFailure: !0 }))
|
|
752
|
+
return !1;
|
|
753
|
+
const n = this.blockStates[t];
|
|
754
|
+
return (n == null ? void 0 : n.recommendationConfigs.strategyId) !== e ? !1 : (r.size !== void 0 && (n.recommendationConfigs = {
|
|
755
|
+
...n.recommendationConfigs,
|
|
756
|
+
size: String(r.size)
|
|
757
|
+
}), !0);
|
|
758
|
+
},
|
|
759
|
+
_doFetchStrategyProducts(t, e = {}) {
|
|
760
|
+
const r = (m.get(t) ?? 0) + 1;
|
|
761
|
+
m.set(t, r);
|
|
762
|
+
const n = this._loadStrategyProducts(t, r, e);
|
|
763
|
+
return D.set(t, { token: r, outcome: n }), n;
|
|
764
|
+
},
|
|
765
|
+
async _loadStrategyProducts(t, e, { keepOnFailure: r = !1 }) {
|
|
766
|
+
const { recommendationConfigs: n } = this.blockStates[t];
|
|
767
|
+
let s = [], i = parseInt(n.size) || 6;
|
|
734
768
|
try {
|
|
735
769
|
await this.fetchStrategies();
|
|
736
|
-
const
|
|
737
|
-
(
|
|
770
|
+
const o = this.strategies.find(
|
|
771
|
+
(a) => String(a.strategy_id) === n.strategyId
|
|
738
772
|
);
|
|
739
|
-
if (
|
|
740
|
-
|
|
741
|
-
const
|
|
742
|
-
|
|
773
|
+
if (o) {
|
|
774
|
+
i = parseInt(String(o.size ?? "")) || i;
|
|
775
|
+
const a = n.currencySettings.value, c = (await this.resolveStrategyUrlTemplate(o, a)).replaceAll("{locale}", n.language).replaceAll("{currency}", a), d = c.indexOf("?"), h = d === -1 ? c : c.slice(0, d), g = (d === -1 ? "" : c.slice(d + 1)).split("&").filter((F) => F && !F.startsWith("user_id=")), v = g.length ? `${h}?${g.join("&")}` : h;
|
|
776
|
+
v && (s = await u.fetchRecommendationProductsByUrl(v));
|
|
743
777
|
}
|
|
744
778
|
} catch {
|
|
745
|
-
|
|
779
|
+
s = [];
|
|
746
780
|
}
|
|
747
|
-
|
|
781
|
+
return m.get(t) !== e ? X(t) : !s.length && r ? !1 : (this._setBlockProducts(t, s, i), s.length > 0);
|
|
748
782
|
},
|
|
749
783
|
_setBlockProducts(t, e, r) {
|
|
750
784
|
if (!this.blockStates[t])
|
|
751
785
|
return;
|
|
752
|
-
const n = e.length > 0 ? e :
|
|
786
|
+
const n = e.length > 0 ? e : P(r);
|
|
753
787
|
this.blockStates[t].recommendationProducts = [
|
|
754
788
|
...n.slice(0, r),
|
|
755
|
-
...
|
|
789
|
+
...P(Math.max(0, r - n.length))
|
|
756
790
|
];
|
|
757
791
|
}
|
|
758
792
|
}
|
|
759
793
|
});
|
|
760
794
|
export {
|
|
761
|
-
|
|
795
|
+
St as useRecommendationExtensionStore
|
|
762
796
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { RRS_CONFIG_VERSION as d, DEFAULT_CURRENCY as t, DEFAULT_NODE_CONFIG as e } from "../constants/defaultConfig.js";
|
|
2
|
+
import { mapLegacyStrategy as n } from "./legacyStrategyMap.js";
|
|
3
|
+
function S(r) {
|
|
4
|
+
var a, u, c, s, l, o;
|
|
5
|
+
const y = !!r.strategyId || (r.configVersion ?? 0) >= d;
|
|
6
|
+
return {
|
|
7
|
+
strategy: n(r.strategy) || (y ? "" : e.strategy),
|
|
8
|
+
strategyId: r.strategyId ?? e.strategyId,
|
|
9
|
+
language: r.language ?? e.language,
|
|
10
|
+
size: r.size ?? e.size,
|
|
11
|
+
// Copied: the source can be a live node config or the shared defaults.
|
|
12
|
+
productIds: [...r.productIds ?? e.productIds],
|
|
13
|
+
filters: structuredClone(r.filters ?? e.filters),
|
|
14
|
+
shuffleProducts: r.shuffleProducts ?? e.shuffleProducts,
|
|
15
|
+
currencyCode: ((a = r.currency) == null ? void 0 : a.code) ?? t.code,
|
|
16
|
+
currencySymbol: ((u = r.currency) == null ? void 0 : u.symbol) ?? t.symbol,
|
|
17
|
+
currencyAlignment: ((c = r.currency) == null ? void 0 : c.alignment) ?? t.alignment,
|
|
18
|
+
currencyDecimalCount: ((s = r.currency) == null ? void 0 : s.decimalCount) ?? t.decimalCount,
|
|
19
|
+
currencyDecimalSeparator: ((l = r.currency) == null ? void 0 : l.decimalSeparator) ?? t.decimalSeparator,
|
|
20
|
+
currencyThousandSeparator: ((o = r.currency) == null ? void 0 : o.thousandSeparator) ?? t.thousandSeparator
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
S as toBlockUrlConfig
|
|
25
|
+
};
|
|
@@ -1,32 +1,37 @@
|
|
|
1
|
-
import { ModificationDescription as
|
|
2
|
-
import { RECOMMENDATION_ID_ATTR as
|
|
3
|
-
import { isPartnerManagedBlock as
|
|
4
|
-
import { RecommendationConfigService as
|
|
5
|
-
let
|
|
6
|
-
function
|
|
7
|
-
|
|
1
|
+
import { ModificationDescription as m } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
2
|
+
import { RECOMMENDATION_ID_ATTR as a } from "../constants/selectors.js";
|
|
3
|
+
import { isPartnerManagedBlock as C, updateProductContentInPlace as N, regenerateProductRowsWithStyles as p } from "../controls/main/utils.js";
|
|
4
|
+
import { RecommendationConfigService as l } from "../services/configService.js";
|
|
5
|
+
let e = null;
|
|
6
|
+
function O(n) {
|
|
7
|
+
e = n;
|
|
8
8
|
}
|
|
9
|
-
function
|
|
10
|
-
const
|
|
11
|
-
|
|
9
|
+
function R(n) {
|
|
10
|
+
const o = e == null ? void 0 : e.getDocumentRootHtmlNode();
|
|
11
|
+
return !o || !("querySelectorAll" in o) ? [] : o.querySelectorAll(`[${a}="${n}"]`).map((i) => l.getConfig(i));
|
|
12
|
+
}
|
|
13
|
+
function P(n, o, i, u) {
|
|
14
|
+
const c = e == null ? void 0 : e.getDocumentRootHtmlNode();
|
|
15
|
+
if (!e || !c || !("querySelector" in c))
|
|
12
16
|
return !1;
|
|
13
|
-
const
|
|
14
|
-
if (!
|
|
17
|
+
const t = c.querySelector(`[${a}="${n}"]`);
|
|
18
|
+
if (!t)
|
|
15
19
|
return !1;
|
|
16
|
-
const
|
|
17
|
-
if (
|
|
18
|
-
return
|
|
20
|
+
const r = e.getDocumentModifier(), d = l.getConfig(t), s = Object.keys(o).some((g) => JSON.stringify(d[g]) !== JSON.stringify(o[g]));
|
|
21
|
+
if (l.stageConfig(r, t, o), C(t))
|
|
22
|
+
return r.apply(new m(u)), !0;
|
|
19
23
|
let f = !1;
|
|
20
|
-
return
|
|
21
|
-
currentNode:
|
|
22
|
-
documentModifier:
|
|
23
|
-
products:
|
|
24
|
+
return N({
|
|
25
|
+
currentNode: t,
|
|
26
|
+
documentModifier: r,
|
|
27
|
+
products: i,
|
|
24
28
|
onApplied: () => {
|
|
25
29
|
f = !0;
|
|
26
30
|
}
|
|
27
|
-
}) || (f =
|
|
31
|
+
}) || (f = p({ currentNode: t, documentModifier: r, products: i })), !f && s && r.apply(new m(u)), !0;
|
|
28
32
|
}
|
|
29
33
|
export {
|
|
30
34
|
P as commitBlockChangeOutsidePanel,
|
|
31
|
-
|
|
35
|
+
R as readBlockNodeConfigs,
|
|
36
|
+
O as registerNodeConfigWriter
|
|
32
37
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ATTR_CUSTOM_PREFIX as f } from "../constants/selectors.js";
|
|
2
|
+
function o(t) {
|
|
3
|
+
if (typeof t == "string")
|
|
4
|
+
return t.trim() !== "";
|
|
5
|
+
if (t && typeof t == "object" && "strategyId" in t) {
|
|
6
|
+
const { strategyId: r } = t;
|
|
7
|
+
return (typeof r == "string" || typeof r == "number") && String(r).trim() !== "";
|
|
8
|
+
}
|
|
9
|
+
return !1;
|
|
10
|
+
}
|
|
11
|
+
function u({ config: t, blockId: r, partnerName: e, campaignUrls: n, rrsEnabled: i }) {
|
|
12
|
+
return e ? t.partnerName ? t.partnerName !== e : !i || !t.strategyId || !n ? !1 : !o(n[String(r)]) : !1;
|
|
13
|
+
}
|
|
14
|
+
function a({ config: t, campaignUrls: r, rrsEnabled: e }) {
|
|
15
|
+
return !t.strategyId || e && !!r;
|
|
16
|
+
}
|
|
17
|
+
function g(t) {
|
|
18
|
+
return t.filter((r) => !r.startsWith(f));
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
a as canJudgeUnstampedBlock,
|
|
22
|
+
u as carriesForeignPartnerConfig,
|
|
23
|
+
o as isDefinedCampaignUrl,
|
|
24
|
+
g as withoutCustomAttributes
|
|
25
|
+
};
|