@useinsider/guido 3.18.1-beta.dea994d → 3.18.1-beta.e489d08
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Guido.vue.js +3 -3
- package/dist/components/Guido.vue2.js +30 -30
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +13 -11
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +65 -53
- package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +20 -18
- package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +21 -0
- package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +47 -0
- package/dist/composables/useCustomInterfaceAppearance.js +46 -41
- package/dist/composables/useHtmlValidator.js +84 -79
- package/dist/composables/usePreviewMode.js +11 -12
- package/dist/composables/useRecommendation.js +21 -18
- package/dist/composables/useStripo.js +7 -7
- package/dist/config/compiler/htmlCompilerRules.js +6 -14
- package/dist/enums/extensions/recommendationBlock.js +38 -31
- package/dist/extensions/Blocks/Recommendation/block.js +43 -39
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +62 -57
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +80 -52
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +150 -73
- package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +21 -12
- package/dist/guido.css +1 -1
- package/dist/src/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.d.ts +2 -0
- package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +2 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +9 -0
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +61 -0
- package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +4 -0
- package/dist/src/stores/onboarding.d.ts +377 -0
- package/dist/static/styles/components/recommendation-strategy.css.js +51 -4
- package/dist/static/styles/customEditorStyle.css.js +0 -14
- package/dist/stores/onboarding.js +41 -36
- package/dist/utils/templatePreparation.js +50 -50
- package/package.json +1 -1
- package/dist/src/utils/appendMobileHiddenColumnCss.d.ts +0 -2
- package/dist/utils/appendMobileHiddenColumnCss.js +0 -11
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import { getRecommendationFeedSourceMaps as
|
|
2
|
-
import { useRecommendationApi as
|
|
1
|
+
import { getRecommendationFeedSourceMaps as k, strategyEditPath as G, URLS as D, getOperatorOptions as _, PriceAttributes as L } from "../../../../enums/extensions/recommendationBlock.js";
|
|
2
|
+
import { useRecommendationApi as E } from "../../../../services/recommendationApi.js";
|
|
3
3
|
import { useConfigStore as P } from "../../../../stores/config.js";
|
|
4
|
-
import { defineStore as
|
|
4
|
+
import { defineStore as N } from "pinia";
|
|
5
5
|
import "../constants/selectors.js";
|
|
6
|
-
import { DEFAULT_MOBILE_CARDS_IN_ROW as
|
|
7
|
-
import { DEFAULT_NODE_CONFIG as
|
|
8
|
-
import { getDefaultProducts as
|
|
9
|
-
import { generateCompleteFilterQuery as
|
|
10
|
-
import { getPartnerRecommendationParams as
|
|
11
|
-
import { sanitizeProductIds as
|
|
12
|
-
import { isFilterValid as
|
|
13
|
-
import { isConfigValid as
|
|
14
|
-
const
|
|
15
|
-
let
|
|
16
|
-
const
|
|
17
|
-
|
|
6
|
+
import { DEFAULT_MOBILE_CARDS_IN_ROW as U, DEFAULT_CARDS_IN_ROW as A } from "../constants/layout.js";
|
|
7
|
+
import { DEFAULT_NODE_CONFIG as x, EXCLUDED_ALGORITHM_IDS as B } from "../constants/defaultConfig.js";
|
|
8
|
+
import { getDefaultProducts as C } from "../templates/utils.js";
|
|
9
|
+
import { generateCompleteFilterQuery as v } from "../utils/filterUtil.js";
|
|
10
|
+
import { getPartnerRecommendationParams as M } from "../utils/partnerCustomizations.js";
|
|
11
|
+
import { sanitizeProductIds as O } from "../utils/productIds.js";
|
|
12
|
+
import { isFilterValid as T } from "../validation/filterSchema.js";
|
|
13
|
+
import { getInvalidFields as z, isConfigValid as V } from "../validation/requiredFields.js";
|
|
14
|
+
const d = E();
|
|
15
|
+
let h = null, g = null, S = null, p = null, y = 0;
|
|
16
|
+
const b = /* @__PURE__ */ new Map();
|
|
17
|
+
let u = null;
|
|
18
|
+
function F() {
|
|
18
19
|
return {
|
|
19
|
-
cardsInRow:
|
|
20
|
+
cardsInRow: A,
|
|
20
21
|
currencySettings: {
|
|
21
22
|
name: "USD",
|
|
22
23
|
value: "USD",
|
|
@@ -30,13 +31,17 @@ 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: [],
|
|
37
38
|
sendProductRequestFlag: !1,
|
|
38
39
|
shuffleProducts: !1,
|
|
39
|
-
|
|
40
|
+
// With RRS on, a block that has not been synced yet must not claim an algorithm:
|
|
41
|
+
// that default is what reached buildCampaignUrl and baked a most-popular feed URL
|
|
42
|
+
// for a block the user never configured (SD-149916). Legacy blocks still get their real
|
|
43
|
+
// algorithm from the node-config sync or the save-time seed.
|
|
44
|
+
strategy: P().isFeatureEnabled("reusableRecommendationStrategy") ? "" : "mostPopular",
|
|
40
45
|
strategyId: "",
|
|
41
46
|
textTrimming: !0,
|
|
42
47
|
unresponsive: !1,
|
|
@@ -46,9 +51,9 @@ function w() {
|
|
|
46
51
|
priceHideIfSameAsDiscounted: !1
|
|
47
52
|
};
|
|
48
53
|
}
|
|
49
|
-
function
|
|
54
|
+
function w() {
|
|
50
55
|
return {
|
|
51
|
-
recommendationConfigs:
|
|
56
|
+
recommendationConfigs: F(),
|
|
52
57
|
recommendationProducts: [],
|
|
53
58
|
filterStatus: !1,
|
|
54
59
|
filterSelectionDrawerStatus: !1,
|
|
@@ -59,7 +64,7 @@ function C() {
|
|
|
59
64
|
filterSnapshot: null
|
|
60
65
|
};
|
|
61
66
|
}
|
|
62
|
-
const
|
|
67
|
+
const j = () => ({
|
|
63
68
|
recommendationCampaignUrls: {},
|
|
64
69
|
activePredictiveAlgorithms: [],
|
|
65
70
|
languages: {},
|
|
@@ -68,11 +73,13 @@ const z = () => ({
|
|
|
68
73
|
strategies: [],
|
|
69
74
|
strategiesLoading: !1,
|
|
70
75
|
strategyUrlTemplates: {},
|
|
76
|
+
strategiesFetched: !1,
|
|
71
77
|
blockStates: {},
|
|
72
78
|
currentRecommendationId: null,
|
|
79
|
+
strategyPanelOpen: !1,
|
|
73
80
|
configVersion: 0
|
|
74
|
-
}),
|
|
75
|
-
state: () =>
|
|
81
|
+
}), nt = N("guidoRecommendationExtension", {
|
|
82
|
+
state: () => j(),
|
|
76
83
|
getters: {
|
|
77
84
|
// ====================================================================
|
|
78
85
|
// Proxy Getters — Backward Compatible Access to Current Block State
|
|
@@ -82,7 +89,7 @@ const z = () => ({
|
|
|
82
89
|
* This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
|
|
83
90
|
*/
|
|
84
91
|
recommendationConfigs(t) {
|
|
85
|
-
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs :
|
|
92
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : F();
|
|
86
93
|
},
|
|
87
94
|
/**
|
|
88
95
|
* Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
|
|
@@ -137,8 +144,8 @@ const z = () => ({
|
|
|
137
144
|
return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
|
|
138
145
|
},
|
|
139
146
|
getActivePredictiveAlgorithms: (t) => {
|
|
140
|
-
const e =
|
|
141
|
-
return t.activePredictiveAlgorithms.filter((n) => !
|
|
147
|
+
const e = k(), r = [];
|
|
148
|
+
return t.activePredictiveAlgorithms.filter((n) => !B.includes(n)).forEach((n) => {
|
|
142
149
|
r.push(...e.filter((s) => s.id === n));
|
|
143
150
|
}), r.map((n) => ({
|
|
144
151
|
text: n.name,
|
|
@@ -156,7 +163,7 @@ const z = () => ({
|
|
|
156
163
|
getFilterList() {
|
|
157
164
|
return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
|
|
158
165
|
let e;
|
|
159
|
-
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` :
|
|
166
|
+
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : L.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
|
|
160
167
|
text: t.displayName,
|
|
161
168
|
value: e,
|
|
162
169
|
type: t.attributeType
|
|
@@ -178,7 +185,7 @@ const z = () => ({
|
|
|
178
185
|
setCurrentBlock(t) {
|
|
179
186
|
this.blockStates[t] || (this.blockStates = {
|
|
180
187
|
...this.blockStates,
|
|
181
|
-
[t]:
|
|
188
|
+
[t]: w()
|
|
182
189
|
}), this.currentRecommendationId = t;
|
|
183
190
|
},
|
|
184
191
|
/**
|
|
@@ -246,7 +253,7 @@ const z = () => ({
|
|
|
246
253
|
decimalCount: String(e.currencyDecimalCount),
|
|
247
254
|
decimalSeparator: r(e.currencyDecimalSeparator, ","),
|
|
248
255
|
thousandSeparator: r(e.currencyThousandSeparator, ".")
|
|
249
|
-
}, s = !this.blockStates[t], i = s ?
|
|
256
|
+
}, s = !this.blockStates[t], i = s ? w() : this.blockStates[t];
|
|
250
257
|
i.recommendationConfigs = {
|
|
251
258
|
...i.recommendationConfigs,
|
|
252
259
|
strategy: e.strategy,
|
|
@@ -285,7 +292,7 @@ const z = () => ({
|
|
|
285
292
|
* Creates a filter with the first available attribute and operator pre-selected.
|
|
286
293
|
*/
|
|
287
294
|
createDefaultFilter(t, e) {
|
|
288
|
-
const [r] = this.getFilterList, [n] =
|
|
295
|
+
const [r] = this.getFilterList, [n] = _(r == null ? void 0 : r.type);
|
|
289
296
|
return {
|
|
290
297
|
type: "standardFilter",
|
|
291
298
|
attribute: (r == null ? void 0 : r.value) ?? "",
|
|
@@ -345,29 +352,87 @@ const z = () => ({
|
|
|
345
352
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !1);
|
|
346
353
|
},
|
|
347
354
|
async fetchStrategies() {
|
|
348
|
-
if (
|
|
349
|
-
await S;
|
|
355
|
+
if (p && await p, this.strategiesFetched)
|
|
350
356
|
return;
|
|
351
|
-
|
|
352
|
-
|
|
357
|
+
const t = y;
|
|
358
|
+
p = (async () => {
|
|
353
359
|
this.strategiesLoading = !0;
|
|
354
360
|
try {
|
|
355
|
-
|
|
361
|
+
const e = await d.fetchRecommendationStrategies();
|
|
362
|
+
if (t !== y)
|
|
363
|
+
return;
|
|
364
|
+
this.strategies = e, this.strategiesFetched = !0;
|
|
356
365
|
} finally {
|
|
357
366
|
this.strategiesLoading = !1;
|
|
358
367
|
}
|
|
359
368
|
})();
|
|
360
369
|
try {
|
|
361
|
-
await
|
|
370
|
+
await p;
|
|
362
371
|
} finally {
|
|
363
|
-
|
|
372
|
+
p = null;
|
|
364
373
|
}
|
|
365
374
|
},
|
|
375
|
+
invalidateStrategies() {
|
|
376
|
+
this.strategiesFetched = !1, y += 1;
|
|
377
|
+
},
|
|
378
|
+
/**
|
|
379
|
+
* Opens a Smart Recommender strategy page in a new tab and refreshes the list every time
|
|
380
|
+
* the user comes back. `visibilitychange` covers the tab case; `focus` covers the page
|
|
381
|
+
* landing in a separate window, where this document never goes hidden.
|
|
382
|
+
*
|
|
383
|
+
* Deliberately NOT one-shot: the strategy tab stays open, so a user can create a second
|
|
384
|
+
* strategy in it and come back again — a listener that disarmed on the first return would
|
|
385
|
+
* leave that one missing from the list. Armed only once the user actually opens a strategy
|
|
386
|
+
* page, so anyone who never does pays nothing.
|
|
387
|
+
*/
|
|
388
|
+
_armStrategyPageReturn(t) {
|
|
389
|
+
window.open(t, "_blank", "noopener"), u == null || u();
|
|
390
|
+
let e = !1;
|
|
391
|
+
const r = () => {
|
|
392
|
+
document.hidden || e || (e = !0, this.invalidateStrategies(), this.fetchStrategies().then(() => this._refreshAssignedStrategyProducts()).catch(() => {
|
|
393
|
+
}).finally(() => {
|
|
394
|
+
e = !1;
|
|
395
|
+
}));
|
|
396
|
+
};
|
|
397
|
+
document.addEventListener("visibilitychange", r), window.addEventListener("focus", r), u = () => {
|
|
398
|
+
document.removeEventListener("visibilitychange", r), window.removeEventListener("focus", r), u = null;
|
|
399
|
+
};
|
|
400
|
+
},
|
|
401
|
+
/**
|
|
402
|
+
* Reloads the products of the block the user is on, so an edit made in the strategy tab
|
|
403
|
+
* lands on the canvas instead of waiting for the assign drawer to be reopened.
|
|
404
|
+
*
|
|
405
|
+
* Only the selected block: the canvas regeneration is driven off the active block's
|
|
406
|
+
* product array, so refreshing an unselected block would fetch without redrawing it.
|
|
407
|
+
*/
|
|
408
|
+
async _refreshAssignedStrategyProducts() {
|
|
409
|
+
var e;
|
|
410
|
+
const t = this.currentRecommendationId;
|
|
411
|
+
t === null || !((e = this.blockStates[t]) != null && e.recommendationConfigs.strategyId) || await this.fetchRecommendationProducts();
|
|
412
|
+
},
|
|
413
|
+
/** Lets the editor tear the return listeners down when it unmounts. */
|
|
414
|
+
disposeStrategyPageReturn() {
|
|
415
|
+
u == null || u();
|
|
416
|
+
},
|
|
417
|
+
/**
|
|
418
|
+
* Opens Smart Recommender's strategy creation page. Every return refreshes the list so the
|
|
419
|
+
* new strategy is offered; the user picks it themselves.
|
|
420
|
+
*/
|
|
421
|
+
openStrategyCreation() {
|
|
422
|
+
this._armStrategyPageReturn(D.RECOMMENDATION_STRATEGY_CREATE_PATH);
|
|
423
|
+
},
|
|
424
|
+
/**
|
|
425
|
+
* Opens the strategy's edit page. Every return refreshes the list so the block reflects the
|
|
426
|
+
* edited configuration.
|
|
427
|
+
*/
|
|
428
|
+
openStrategyEdit(t) {
|
|
429
|
+
this._armStrategyPageReturn(G(t));
|
|
430
|
+
},
|
|
366
431
|
async resolveStrategyUrlTemplate(t, e) {
|
|
367
432
|
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
433
|
if (s)
|
|
369
434
|
return s;
|
|
370
|
-
const { full_path: i = "" } = await
|
|
435
|
+
const { full_path: i = "" } = await d.generateStrategyEndpoint(t, e) ?? {};
|
|
371
436
|
return n && i && (this.strategyUrlTemplates = {
|
|
372
437
|
...this.strategyUrlTemplates,
|
|
373
438
|
[n]: i
|
|
@@ -380,23 +445,23 @@ const z = () => ({
|
|
|
380
445
|
});
|
|
381
446
|
},
|
|
382
447
|
removeStrategy() {
|
|
383
|
-
this.patchCurrentBlockConfig({ strategyId: "", size:
|
|
448
|
+
this.patchCurrentBlockConfig({ strategyId: "", size: x.size });
|
|
384
449
|
},
|
|
385
450
|
// ====================================================================
|
|
386
451
|
// Shared Data Fetching (fetched once, used by all blocks)
|
|
387
452
|
// ====================================================================
|
|
388
453
|
async fetchRecommendationCreateData() {
|
|
389
454
|
if (!this.activePredictiveAlgorithms.length) {
|
|
390
|
-
if (
|
|
391
|
-
await
|
|
455
|
+
if (h) {
|
|
456
|
+
await h;
|
|
392
457
|
return;
|
|
393
458
|
}
|
|
394
|
-
|
|
459
|
+
h = (async () => {
|
|
395
460
|
const {
|
|
396
461
|
activePredictiveAlgorithms: t,
|
|
397
462
|
languages: e,
|
|
398
463
|
currencies: r
|
|
399
|
-
} = await
|
|
464
|
+
} = await d.fetchRecommendationCreateData();
|
|
400
465
|
if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
|
|
401
466
|
const n = this.blockStates[this.currentRecommendationId];
|
|
402
467
|
n.filterStatus = !!n.recommendationConfigs.filters.length;
|
|
@@ -404,26 +469,26 @@ const z = () => ({
|
|
|
404
469
|
this.currencyList = r;
|
|
405
470
|
})();
|
|
406
471
|
try {
|
|
407
|
-
await
|
|
472
|
+
await h;
|
|
408
473
|
} finally {
|
|
409
|
-
|
|
474
|
+
h = null;
|
|
410
475
|
}
|
|
411
476
|
}
|
|
412
477
|
},
|
|
413
478
|
async fetchRecommendationFilters() {
|
|
414
479
|
if (!Object.keys(this.filterList).length) {
|
|
415
|
-
if (
|
|
416
|
-
await
|
|
480
|
+
if (g) {
|
|
481
|
+
await g;
|
|
417
482
|
return;
|
|
418
483
|
}
|
|
419
|
-
|
|
420
|
-
const t = await
|
|
484
|
+
g = (async () => {
|
|
485
|
+
const t = await d.fetchRecommendationFilters();
|
|
421
486
|
this.filterList = t;
|
|
422
487
|
})();
|
|
423
488
|
try {
|
|
424
|
-
await
|
|
489
|
+
await g;
|
|
425
490
|
} finally {
|
|
426
|
-
|
|
491
|
+
g = null;
|
|
427
492
|
}
|
|
428
493
|
}
|
|
429
494
|
},
|
|
@@ -452,7 +517,7 @@ const z = () => ({
|
|
|
452
517
|
const n = [...e.recommendationConfigs.filters];
|
|
453
518
|
n[r] = {
|
|
454
519
|
...t,
|
|
455
|
-
isValid:
|
|
520
|
+
isValid: T(t)
|
|
456
521
|
}, e.recommendationConfigs.filters = n;
|
|
457
522
|
}
|
|
458
523
|
},
|
|
@@ -490,7 +555,7 @@ const z = () => ({
|
|
|
490
555
|
}), e.recommendationConfigs.filters = r;
|
|
491
556
|
},
|
|
492
557
|
generateFilterQuery() {
|
|
493
|
-
return
|
|
558
|
+
return v(this.recommendationConfigs.filters);
|
|
494
559
|
},
|
|
495
560
|
/**
|
|
496
561
|
* Validation-only check invoked at save-CTA time. Defined as an action
|
|
@@ -498,33 +563,45 @@ const z = () => ({
|
|
|
498
563
|
* every block's recommendationConfigs across user edits.
|
|
499
564
|
*/
|
|
500
565
|
hasInvalidBlock() {
|
|
501
|
-
return Object.values(this.blockStates).some((t) => !
|
|
566
|
+
return Object.values(this.blockStates).some((t) => !V(t.recommendationConfigs, this));
|
|
567
|
+
},
|
|
568
|
+
/**
|
|
569
|
+
* Which required fields are missing across the design's blocks, so the save
|
|
570
|
+
* toaster can name the cause instead of always showing the generic message.
|
|
571
|
+
*/
|
|
572
|
+
invalidBlockFields() {
|
|
573
|
+
return Object.values(this.blockStates).flatMap((t) => z(t.recommendationConfigs, this));
|
|
502
574
|
},
|
|
503
575
|
// ====================================================================
|
|
504
576
|
// Per-Block Product Fetching
|
|
505
577
|
// ====================================================================
|
|
506
578
|
async fetchRecommendationProducts() {
|
|
507
579
|
if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
|
|
508
|
-
if (
|
|
509
|
-
await
|
|
580
|
+
if (S) {
|
|
581
|
+
await S;
|
|
510
582
|
return;
|
|
511
583
|
}
|
|
512
|
-
|
|
584
|
+
S = this._doFetchProducts();
|
|
513
585
|
try {
|
|
514
|
-
await
|
|
586
|
+
await S;
|
|
515
587
|
} finally {
|
|
516
|
-
|
|
588
|
+
S = null;
|
|
517
589
|
}
|
|
518
590
|
}
|
|
519
591
|
},
|
|
520
592
|
async _doFetchProducts() {
|
|
521
|
-
var
|
|
593
|
+
var f;
|
|
522
594
|
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = P();
|
|
523
595
|
if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
|
|
524
596
|
await this._doFetchStrategyProducts(t);
|
|
525
597
|
return;
|
|
526
598
|
}
|
|
527
|
-
const s =
|
|
599
|
+
const s = parseInt(r.size) || 6;
|
|
600
|
+
if (!r.strategy) {
|
|
601
|
+
this._setBlockProducts(t, [], s);
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
const i = r.filters.filter((m) => m.isValid), o = v(i), c = ((f = k().find((m) => m.key === r.strategy)) == null ? void 0 : f.path) || "", a = {
|
|
528
605
|
locale: r.language,
|
|
529
606
|
currency: r.currencySettings.value,
|
|
530
607
|
partnerName: n.partnerName,
|
|
@@ -532,21 +609,21 @@ const z = () => ({
|
|
|
532
609
|
details: !0,
|
|
533
610
|
campaignId: n.variationId
|
|
534
611
|
};
|
|
535
|
-
r.strategy === "manualMerchandising" ? a.productId =
|
|
612
|
+
r.strategy === "manualMerchandising" ? a.productId = O(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), o && (a.filter = o), r.shuffleProducts && (a.shuffle = !0), Object.assign(
|
|
536
613
|
a,
|
|
537
|
-
|
|
614
|
+
M(n.partnerName, r.strategy)
|
|
538
615
|
);
|
|
539
616
|
let l;
|
|
540
617
|
try {
|
|
541
|
-
l = await
|
|
618
|
+
l = await d.fetchRecommendationProducts(c, a);
|
|
542
619
|
} catch {
|
|
543
620
|
l = [];
|
|
544
621
|
}
|
|
545
|
-
this._setBlockProducts(t, l,
|
|
622
|
+
this._setBlockProducts(t, l, s);
|
|
546
623
|
},
|
|
547
624
|
async _doFetchStrategyProducts(t) {
|
|
548
|
-
const e = (
|
|
549
|
-
|
|
625
|
+
const e = (b.get(t) ?? 0) + 1;
|
|
626
|
+
b.set(t, e);
|
|
550
627
|
const { recommendationConfigs: r } = this.blockStates[t];
|
|
551
628
|
let n = [], s = parseInt(r.size) || 6;
|
|
552
629
|
try {
|
|
@@ -556,25 +633,25 @@ const z = () => ({
|
|
|
556
633
|
);
|
|
557
634
|
if (i) {
|
|
558
635
|
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("?"),
|
|
560
|
-
|
|
636
|
+
const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), f = l === -1 ? a : a.slice(0, l), m = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((R) => R && !R.startsWith("user_id=")), I = m.length ? `${f}?${m.join("&")}` : f;
|
|
637
|
+
I && (n = await d.fetchRecommendationProductsByUrl(I));
|
|
561
638
|
}
|
|
562
639
|
} catch {
|
|
563
640
|
n = [];
|
|
564
641
|
}
|
|
565
|
-
|
|
642
|
+
b.get(t) === e && this._setBlockProducts(t, n, s);
|
|
566
643
|
},
|
|
567
644
|
_setBlockProducts(t, e, r) {
|
|
568
645
|
if (!this.blockStates[t])
|
|
569
646
|
return;
|
|
570
|
-
const n = e.length > 0 ? e :
|
|
647
|
+
const n = e.length > 0 ? e : C(r);
|
|
571
648
|
this.blockStates[t].recommendationProducts = [
|
|
572
649
|
...n.slice(0, r),
|
|
573
|
-
...
|
|
650
|
+
...C(Math.max(0, r - n.length))
|
|
574
651
|
];
|
|
575
652
|
}
|
|
576
653
|
}
|
|
577
654
|
});
|
|
578
655
|
export {
|
|
579
|
-
|
|
656
|
+
nt as useRecommendationExtensionStore
|
|
580
657
|
};
|
|
@@ -1,34 +1,43 @@
|
|
|
1
|
-
const
|
|
1
|
+
const o = "strategy", u = [
|
|
2
2
|
{
|
|
3
3
|
key: "locale",
|
|
4
4
|
getValue: (e) => e.language,
|
|
5
5
|
getAvailableOptions: (e) => Object.keys(e.languages)
|
|
6
6
|
},
|
|
7
|
+
{
|
|
8
|
+
// A block feeds from either an assigned strategy (RRS) or an algorithm (legacy).
|
|
9
|
+
// Only a fresh RRS block has neither, and its feed URL would otherwise be built
|
|
10
|
+
// from an empty algorithm path.
|
|
11
|
+
key: o,
|
|
12
|
+
getValue: (e) => e.strategyId || e.strategy
|
|
13
|
+
},
|
|
7
14
|
{
|
|
8
15
|
key: "currency",
|
|
9
16
|
getValue: (e) => e.currencySettings.value,
|
|
10
17
|
getAvailableOptions: (e) => e.currencyList.map((n) => n.text),
|
|
11
18
|
canBeEmpty: !0
|
|
12
19
|
}
|
|
13
|
-
],
|
|
14
|
-
function c(e, n, i =
|
|
20
|
+
], l = "newsletter.recommendation-fill-required-fields", g = "newsletter.recommendation-assign-strategy";
|
|
21
|
+
function c(e, n, i = u) {
|
|
15
22
|
return i.filter((t) => {
|
|
16
|
-
var
|
|
23
|
+
var s;
|
|
17
24
|
if (t.condition && !t.condition(e))
|
|
18
25
|
return !1;
|
|
19
|
-
const
|
|
20
|
-
if (t.canBeEmpty && (
|
|
26
|
+
const a = (s = t.getAvailableOptions) == null ? void 0 : s.call(t, n);
|
|
27
|
+
if (t.canBeEmpty && (a == null ? void 0 : a.length) === 0)
|
|
21
28
|
return !1;
|
|
22
|
-
const
|
|
23
|
-
return
|
|
29
|
+
const r = t.getValue(e);
|
|
30
|
+
return r ? a !== void 0 && !a.includes(r) : !0;
|
|
24
31
|
}).map((t) => t.key);
|
|
25
32
|
}
|
|
26
|
-
function
|
|
33
|
+
function y(e, n) {
|
|
27
34
|
return c(e, n).length === 0;
|
|
28
35
|
}
|
|
29
36
|
export {
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
u as REQUIRED_RECOMMENDATION_FIELDS,
|
|
38
|
+
g as RecommendationAssignStrategyKey,
|
|
39
|
+
l as RecommendationRequiredFieldsKey,
|
|
40
|
+
o as STRATEGY_FIELD_KEY,
|
|
32
41
|
c as getInvalidFields,
|
|
33
|
-
|
|
42
|
+
y as isConfigValid
|
|
34
43
|
};
|
package/dist/guido.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@charset "UTF-8";.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-1ca6baf0]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-
|
|
1
|
+
@charset "UTF-8";.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-1ca6baf0]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-cc5ee925]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-cc5ee925]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-cc5ee925]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-ec2027ff] .vueperslides__bullets,[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-b447f626]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-b447f626] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
|
|
2
|
+
export default _default;
|
|
@@ -5,7 +5,9 @@ export declare const URLS: {
|
|
|
5
5
|
PRODUCT_ATTRIBUTES_PATH: string;
|
|
6
6
|
RECOMMENDATION_STRATEGIES_PATH: string;
|
|
7
7
|
RECOMMENDATION_STRATEGIES_PANEL_PATH: string;
|
|
8
|
+
RECOMMENDATION_STRATEGY_CREATE_PATH: string;
|
|
8
9
|
};
|
|
10
|
+
export declare const strategyEditPath: (strategyId: string | number) => string;
|
|
9
11
|
export declare const QUERY_PARAMS: {
|
|
10
12
|
CLIENT_ID: string;
|
|
11
13
|
};
|
|
@@ -66,6 +66,8 @@ export declare class RecommendationBlockControl extends CommonControl {
|
|
|
66
66
|
* edits are never clobbered (SD-141049).
|
|
67
67
|
*/
|
|
68
68
|
private _syncNodeConfigIfChanged;
|
|
69
|
+
/** Whether the deferred write would move the node's strategyId — see the caller (SD-149916). */
|
|
70
|
+
private _isPendingStrategyIdChange;
|
|
69
71
|
private _capturePendingNodeConfigWrite;
|
|
70
72
|
/**
|
|
71
73
|
* Accumulates the pending write into `documentModifier` without applying, so the
|
|
@@ -2,6 +2,7 @@ import { CommonControl } from '../../../common-control';
|
|
|
2
2
|
export declare const STRATEGY_CONTROL_ID = "recommendation-strategy-control";
|
|
3
3
|
export declare class StrategyControl extends CommonControl {
|
|
4
4
|
private store;
|
|
5
|
+
private onboardingStore;
|
|
5
6
|
private storeUnsubscription;
|
|
6
7
|
private listeners;
|
|
7
8
|
private lastPaintedState;
|
|
@@ -9,6 +10,14 @@ export declare class StrategyControl extends CommonControl {
|
|
|
9
10
|
getTemplate(): string;
|
|
10
11
|
private _strategyAction;
|
|
11
12
|
onRender(): void;
|
|
13
|
+
/**
|
|
14
|
+
* Whether the document itself says this block has no strategy.
|
|
15
|
+
*
|
|
16
|
+
* Read the node, not the store: when the main control cannot resolve the block id off the
|
|
17
|
+
* node it never syncs the persisted config, so the store still holds defaults (empty
|
|
18
|
+
* strategyId) for an assigned block.
|
|
19
|
+
*/
|
|
20
|
+
private _isNodeUnassigned;
|
|
12
21
|
onDestroy(): void;
|
|
13
22
|
private _teardown;
|
|
14
23
|
private _setupButtonListeners;
|