@useinsider/guido 3.17.0-beta.3ff6ea0 → 3.17.0-beta.6255bfc
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 +1 -0
- package/dist/@types/config/schemas.js +12 -6
- package/dist/components/Guido.vue.js +2 -2
- package/dist/components/Guido.vue2.js +31 -30
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +18 -0
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +66 -0
- package/dist/composables/useCustomInterfaceAppearance.js +52 -38
- package/dist/composables/useRecommendation.js +52 -44
- package/dist/composables/useStripo.js +14 -14
- package/dist/config/migrator/index.js +8 -9
- package/dist/config/migrator/recommendation/compositionMapper.js +20 -20
- package/dist/config/migrator/recommendation/extractors.js +24 -29
- package/dist/config/migrator/recommendation/htmlBuilder.js +130 -116
- package/dist/config/migrator/recommendation/settingsMapper.js +19 -17
- package/dist/config/migrator/recommendationMigrator.js +15 -16
- package/dist/enums/academy.js +2 -1
- package/dist/enums/date.js +4 -3
- package/dist/enums/extensions/recommendationBlock.js +4 -1
- package/dist/extensions/Blocks/Recommendation/block.js +26 -21
- package/dist/extensions/Blocks/Recommendation/constants/blockIds.js +1 -1
- package/dist/extensions/Blocks/Recommendation/constants/controlIds.js +1 -1
- package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +26 -25
- package/dist/extensions/Blocks/Recommendation/constants/selectors.js +28 -34
- package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +256 -323
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +178 -165
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +142 -0
- package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +0 -1
- package/dist/extensions/Blocks/Recommendation/extension.js +29 -31
- package/dist/extensions/Blocks/Recommendation/services/configService.js +35 -35
- package/dist/extensions/Blocks/Recommendation/settingsPanel.js +4 -23
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +251 -110
- package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +3 -3
- package/dist/extensions/Blocks/Recommendation/templates/utils.js +107 -85
- package/dist/extensions/Blocks/common-control.js +22 -19
- package/dist/guido.css +1 -1
- package/dist/services/recommendationApi.js +75 -30
- package/dist/src/@types/config/schemas.d.ts +12 -0
- package/dist/src/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.d.ts +3 -0
- package/dist/src/components/wrappers/WpModal.vue.d.ts +1 -1
- package/dist/src/composables/useConfig.d.ts +2 -0
- package/dist/src/composables/useRecommendation.d.ts +1 -0
- package/dist/src/config/migrator/recommendation/extractors.d.ts +0 -8
- package/dist/src/enums/academy.d.ts +1 -0
- package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
- package/dist/src/extensions/Blocks/Recommendation/constants/blockIds.d.ts +1 -2
- package/dist/src/extensions/Blocks/Recommendation/constants/controlIds.d.ts +0 -7
- package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +7 -7
- package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +2 -2
- package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +0 -10
- package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +0 -10
- package/dist/src/extensions/Blocks/Recommendation/controls/index.d.ts +0 -1
- package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +15 -3
- package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +30 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +0 -1
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +206 -10
- package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +6 -0
- package/dist/src/extensions/Blocks/common-control.d.ts +4 -1
- package/dist/src/mock/api/recommendation-strategies.d.ts +63 -0
- package/dist/src/services/recommendationApi.d.ts +4 -1
- package/dist/src/stores/config.d.ts +18 -0
- package/dist/src/utils/strategyInfoBox.d.ts +22 -0
- package/dist/static/assets/icons/line-change.svg.js +5 -0
- package/dist/static/assets/icons/line-delete.svg.js +5 -0
- package/dist/static/assets/icons/line-plus.svg.js +5 -0
- package/dist/static/styles/components/recommendation-strategy.css.js +188 -0
- package/dist/static/styles/customEditorStyle.css.js +1 -3
- package/dist/utils/dateUtil.js +29 -10
- package/dist/utils/strategyInfoBox.js +37 -0
- package/dist/utils/templatePreparation.js +37 -34
- package/package.json +2 -1
- package/dist/config/migrator/recommendationTitleMigrator.js +0 -119
- package/dist/extensions/Blocks/Recommendation/controls/title/index.js +0 -44
- package/dist/extensions/Blocks/Recommendation/templates/titleRows.js +0 -33
- package/dist/src/config/migrator/recommendationTitleMigrator.d.ts +0 -5
- package/dist/src/extensions/Blocks/Recommendation/controls/title/index.d.ts +0 -86
- package/dist/src/extensions/Blocks/Recommendation/templates/titleRows.d.ts +0 -13
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { useConfig as C } from "../../../../composables/useConfig.js";
|
|
2
|
+
import { getRecommendationFeedSourceMaps as y, getOperatorOptions as w, PriceAttributes as G } from "../../../../enums/extensions/recommendationBlock.js";
|
|
3
|
+
import { useRecommendationApi as D } from "../../../../services/recommendationApi.js";
|
|
4
|
+
import { useConfigStore as P } from "../../../../stores/config.js";
|
|
5
|
+
import { defineStore as F } from "pinia";
|
|
5
6
|
import "../constants/selectors.js";
|
|
6
|
-
import { DEFAULT_MOBILE_CARDS_IN_ROW as
|
|
7
|
-
import { EXCLUDED_ALGORITHM_IDS 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
|
-
function
|
|
7
|
+
import { DEFAULT_MOBILE_CARDS_IN_ROW as v, DEFAULT_CARDS_IN_ROW as _ } from "../constants/layout.js";
|
|
8
|
+
import { DEFAULT_NODE_CONFIG as U, EXCLUDED_ALGORITHM_IDS as N } from "../constants/defaultConfig.js";
|
|
9
|
+
import { getDefaultProducts as b } from "../templates/utils.js";
|
|
10
|
+
import { generateCompleteFilterQuery as I } from "../utils/filterUtil.js";
|
|
11
|
+
import { getPartnerRecommendationParams as L } from "../utils/partnerCustomizations.js";
|
|
12
|
+
import { sanitizeProductIds as x } from "../utils/productIds.js";
|
|
13
|
+
import { isFilterValid as A } from "../validation/filterSchema.js";
|
|
14
|
+
import { isConfigValid as B } from "../validation/requiredFields.js";
|
|
15
|
+
const d = D();
|
|
16
|
+
let f = null, g = null, h = null, S = null;
|
|
17
|
+
function R() {
|
|
17
18
|
return {
|
|
18
|
-
cardsInRow:
|
|
19
|
+
cardsInRow: _,
|
|
19
20
|
currencySettings: {
|
|
20
21
|
name: "USD",
|
|
21
22
|
value: "USD",
|
|
@@ -29,13 +30,14 @@ function k() {
|
|
|
29
30
|
productIds: [],
|
|
30
31
|
id: 1,
|
|
31
32
|
language: "en_US",
|
|
32
|
-
mobileCardsInRow:
|
|
33
|
+
mobileCardsInRow: v,
|
|
33
34
|
mobileLayoutEnabled: !1,
|
|
34
35
|
orientation: "grid",
|
|
35
36
|
recommendedProducts: [],
|
|
36
37
|
sendProductRequestFlag: !1,
|
|
37
38
|
shuffleProducts: !1,
|
|
38
39
|
strategy: "mostPopular",
|
|
40
|
+
strategyId: "",
|
|
39
41
|
textTrimming: !0,
|
|
40
42
|
unresponsive: !1,
|
|
41
43
|
size: "6",
|
|
@@ -44,28 +46,32 @@ function k() {
|
|
|
44
46
|
priceHideIfSameAsDiscounted: !1
|
|
45
47
|
};
|
|
46
48
|
}
|
|
47
|
-
function
|
|
49
|
+
function k() {
|
|
48
50
|
return {
|
|
49
|
-
recommendationConfigs:
|
|
51
|
+
recommendationConfigs: R(),
|
|
50
52
|
recommendationProducts: [],
|
|
51
53
|
filterStatus: !1,
|
|
52
54
|
filterSelectionDrawerStatus: !1,
|
|
55
|
+
assignStrategyDrawerStatus: !1,
|
|
53
56
|
filterGroup: 1,
|
|
54
57
|
isInitialized: !1,
|
|
55
58
|
filterSnapshot: null
|
|
56
59
|
};
|
|
57
60
|
}
|
|
58
|
-
const
|
|
61
|
+
const z = () => ({
|
|
59
62
|
recommendationCampaignUrls: {},
|
|
60
63
|
activePredictiveAlgorithms: [],
|
|
61
64
|
languages: {},
|
|
62
65
|
currencyList: [],
|
|
63
66
|
filterList: {},
|
|
67
|
+
strategies: [],
|
|
68
|
+
strategiesLoading: !1,
|
|
69
|
+
strategyUrlTemplates: {},
|
|
64
70
|
blockStates: {},
|
|
65
71
|
currentRecommendationId: null,
|
|
66
72
|
configVersion: 0
|
|
67
|
-
}),
|
|
68
|
-
state: () =>
|
|
73
|
+
}), Y = F("guidoRecommendationExtension", {
|
|
74
|
+
state: () => z(),
|
|
69
75
|
getters: {
|
|
70
76
|
// ====================================================================
|
|
71
77
|
// Proxy Getters — Backward Compatible Access to Current Block State
|
|
@@ -75,7 +81,7 @@ const U = () => ({
|
|
|
75
81
|
* This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
|
|
76
82
|
*/
|
|
77
83
|
recommendationConfigs(t) {
|
|
78
|
-
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs :
|
|
84
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : R();
|
|
79
85
|
},
|
|
80
86
|
/**
|
|
81
87
|
* Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
|
|
@@ -89,6 +95,20 @@ const U = () => ({
|
|
|
89
95
|
filterSelectionDrawerStatus(t) {
|
|
90
96
|
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].filterSelectionDrawerStatus : !1;
|
|
91
97
|
},
|
|
98
|
+
/**
|
|
99
|
+
* Proxy getter: delegates to blockStates[currentRecommendationId].assignStrategyDrawerStatus
|
|
100
|
+
*/
|
|
101
|
+
assignStrategyDrawerStatus(t) {
|
|
102
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].assignStrategyDrawerStatus : !1;
|
|
103
|
+
},
|
|
104
|
+
/**
|
|
105
|
+
* The current block's assigned strategy record from the listing,
|
|
106
|
+
* or null when nothing is assigned / the strategy is no longer listed.
|
|
107
|
+
*/
|
|
108
|
+
assignedStrategy(t) {
|
|
109
|
+
const { strategyId: e } = this.recommendationConfigs;
|
|
110
|
+
return e ? t.strategies.find((r) => String(r.strategy_id) === e) ?? null : null;
|
|
111
|
+
},
|
|
92
112
|
/**
|
|
93
113
|
* Proxy getter: delegates to blockStates[currentRecommendationId].filterStatus
|
|
94
114
|
*/
|
|
@@ -120,12 +140,12 @@ const U = () => ({
|
|
|
120
140
|
return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
|
|
121
141
|
},
|
|
122
142
|
getActivePredictiveAlgorithms: (t) => {
|
|
123
|
-
const e =
|
|
124
|
-
return t.activePredictiveAlgorithms.filter((
|
|
125
|
-
r.push(...e.filter((
|
|
126
|
-
}), r.map((
|
|
127
|
-
text:
|
|
128
|
-
value:
|
|
143
|
+
const e = y(), r = [];
|
|
144
|
+
return t.activePredictiveAlgorithms.filter((i) => !N.includes(i)).forEach((i) => {
|
|
145
|
+
r.push(...e.filter((s) => s.id === i));
|
|
146
|
+
}), r.map((i) => ({
|
|
147
|
+
text: i.name,
|
|
148
|
+
value: i.key
|
|
129
149
|
}));
|
|
130
150
|
},
|
|
131
151
|
getLanguages: (t) => Object.entries(t.languages).map(([e, r]) => ({
|
|
@@ -139,7 +159,7 @@ const U = () => ({
|
|
|
139
159
|
getFilterList() {
|
|
140
160
|
return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
|
|
141
161
|
let e;
|
|
142
|
-
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` :
|
|
162
|
+
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : G.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
|
|
143
163
|
text: t.displayName,
|
|
144
164
|
value: e,
|
|
145
165
|
type: t.attributeType
|
|
@@ -161,7 +181,7 @@ const U = () => ({
|
|
|
161
181
|
setCurrentBlock(t) {
|
|
162
182
|
this.blockStates[t] || (this.blockStates = {
|
|
163
183
|
...this.blockStates,
|
|
164
|
-
[t]:
|
|
184
|
+
[t]: k()
|
|
165
185
|
}), this.currentRecommendationId = t;
|
|
166
186
|
},
|
|
167
187
|
/**
|
|
@@ -171,13 +191,13 @@ const U = () => ({
|
|
|
171
191
|
removeBlockState(t) {
|
|
172
192
|
const e = t.toString();
|
|
173
193
|
if (this.recommendationCampaignUrls[e]) {
|
|
174
|
-
const
|
|
175
|
-
delete
|
|
194
|
+
const i = { ...this.recommendationCampaignUrls };
|
|
195
|
+
delete i[e], this.recommendationCampaignUrls = i;
|
|
176
196
|
}
|
|
177
197
|
const r = { ...this.blockStates };
|
|
178
198
|
if (delete r[t], this.blockStates = r, this.currentRecommendationId === t) {
|
|
179
|
-
const
|
|
180
|
-
this.currentRecommendationId =
|
|
199
|
+
const i = Object.keys(this.blockStates).map(Number);
|
|
200
|
+
this.currentRecommendationId = i.length > 0 ? i[0] : null;
|
|
181
201
|
}
|
|
182
202
|
},
|
|
183
203
|
/**
|
|
@@ -193,10 +213,10 @@ const U = () => ({
|
|
|
193
213
|
[e]: o
|
|
194
214
|
};
|
|
195
215
|
}
|
|
196
|
-
const
|
|
197
|
-
|
|
216
|
+
const i = t.toString(), s = e.toString(), n = this.recommendationCampaignUrls[i];
|
|
217
|
+
n && (this.recommendationCampaignUrls = {
|
|
198
218
|
...this.recommendationCampaignUrls,
|
|
199
|
-
[
|
|
219
|
+
[s]: n
|
|
200
220
|
});
|
|
201
221
|
},
|
|
202
222
|
/**
|
|
@@ -221,7 +241,7 @@ const U = () => ({
|
|
|
221
241
|
* `isInitialized`) alone.
|
|
222
242
|
*/
|
|
223
243
|
seedBlockUrlConfig(t, e) {
|
|
224
|
-
const r = (o,
|
|
244
|
+
const r = (o, a) => o === "." || o === "," || o === " " ? o : a, i = {
|
|
225
245
|
name: e.currencyCode,
|
|
226
246
|
value: e.currencyCode,
|
|
227
247
|
symbol: e.currencyCode,
|
|
@@ -229,19 +249,20 @@ const U = () => ({
|
|
|
229
249
|
decimalCount: String(e.currencyDecimalCount),
|
|
230
250
|
decimalSeparator: r(e.currencyDecimalSeparator, ","),
|
|
231
251
|
thousandSeparator: r(e.currencyThousandSeparator, ".")
|
|
232
|
-
},
|
|
233
|
-
|
|
234
|
-
...
|
|
252
|
+
}, s = !this.blockStates[t], n = s ? k() : this.blockStates[t];
|
|
253
|
+
n.recommendationConfigs = {
|
|
254
|
+
...n.recommendationConfigs,
|
|
235
255
|
strategy: e.strategy,
|
|
256
|
+
strategyId: e.strategyId,
|
|
236
257
|
language: e.language,
|
|
237
258
|
size: e.size,
|
|
238
259
|
productIds: e.productIds,
|
|
239
260
|
filters: e.filters,
|
|
240
261
|
shuffleProducts: e.shuffleProducts,
|
|
241
|
-
currencySettings:
|
|
242
|
-
},
|
|
262
|
+
currencySettings: i
|
|
263
|
+
}, s && (this.blockStates = {
|
|
243
264
|
...this.blockStates,
|
|
244
|
-
[t]:
|
|
265
|
+
[t]: n
|
|
245
266
|
});
|
|
246
267
|
},
|
|
247
268
|
/**
|
|
@@ -260,18 +281,18 @@ const U = () => ({
|
|
|
260
281
|
...t.currencySettings || {}
|
|
261
282
|
}
|
|
262
283
|
};
|
|
263
|
-
const { triggerRefetch:
|
|
264
|
-
|
|
284
|
+
const { triggerRefetch: i = !0 } = e;
|
|
285
|
+
i && this.configVersion++;
|
|
265
286
|
},
|
|
266
287
|
/**
|
|
267
288
|
* Creates a filter with the first available attribute and operator pre-selected.
|
|
268
289
|
*/
|
|
269
290
|
createDefaultFilter(t, e) {
|
|
270
|
-
const [r] = this.getFilterList, [
|
|
291
|
+
const [r] = this.getFilterList, [i] = w(r == null ? void 0 : r.type);
|
|
271
292
|
return {
|
|
272
293
|
type: "standardFilter",
|
|
273
294
|
attribute: (r == null ? void 0 : r.value) ?? "",
|
|
274
|
-
operator: (
|
|
295
|
+
operator: (i == null ? void 0 : i.value) ?? "",
|
|
275
296
|
innerGroupOperator: "*",
|
|
276
297
|
outerGroupOperator: "*",
|
|
277
298
|
filterNumber: e,
|
|
@@ -315,47 +336,129 @@ const U = () => ({
|
|
|
315
336
|
t.filterSnapshot !== null && (t.recommendationConfigs.filters = t.filterSnapshot, t.filterSnapshot = null), t.filterSelectionDrawerStatus = !1;
|
|
316
337
|
},
|
|
317
338
|
// ====================================================================
|
|
339
|
+
// Reusable Recommendation Strategy (SD-149105)
|
|
340
|
+
// ====================================================================
|
|
341
|
+
/**
|
|
342
|
+
* Opens the Assign Strategy drawer for the current block.
|
|
343
|
+
* Selection state lives in the drawer component until Assign is
|
|
344
|
+
* pressed, so closing without assigning needs no snapshot/revert.
|
|
345
|
+
*/
|
|
346
|
+
openAssignStrategyDrawer() {
|
|
347
|
+
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !0);
|
|
348
|
+
},
|
|
349
|
+
closeAssignStrategyDrawer() {
|
|
350
|
+
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !1);
|
|
351
|
+
},
|
|
352
|
+
/**
|
|
353
|
+
* Fetches the active + EMAIL strategy listing. Always fetches fresh
|
|
354
|
+
* (dead-strategy detection and post-create refresh need freshness);
|
|
355
|
+
* only concurrent in-flight calls share one request.
|
|
356
|
+
*/
|
|
357
|
+
async fetchStrategies() {
|
|
358
|
+
if (S) {
|
|
359
|
+
await S;
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
S = (async () => {
|
|
363
|
+
this.strategiesLoading = !0;
|
|
364
|
+
try {
|
|
365
|
+
this.strategies = await d.fetchRecommendationStrategies();
|
|
366
|
+
} finally {
|
|
367
|
+
this.strategiesLoading = !1;
|
|
368
|
+
}
|
|
369
|
+
})();
|
|
370
|
+
try {
|
|
371
|
+
await S;
|
|
372
|
+
} finally {
|
|
373
|
+
S = null;
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
/**
|
|
377
|
+
* Resolves a strategy's recommendation endpoint template via
|
|
378
|
+
* endpoint-generate, cached per strategy id + revision + currency.
|
|
379
|
+
* Failures throw and are NOT cached, so the next attempt retries.
|
|
380
|
+
*
|
|
381
|
+
* `full_path` bakes in the algorithm path and `size=` as they were when
|
|
382
|
+
* generated, so the revision keys the cache — and a record with no
|
|
383
|
+
* revision is not cached at all, since its key could never change.
|
|
384
|
+
* Currency joins the key because it is sent in the request body, so two
|
|
385
|
+
* currencies can resolve to different paths for the same revision.
|
|
386
|
+
*/
|
|
387
|
+
async resolveStrategyUrlTemplate(t, e) {
|
|
388
|
+
const r = typeof t.updated_at == "string" ? t.updated_at : "", i = r ? `${t.strategy_id}:${r}:${e}` : "", s = i ? this.strategyUrlTemplates[i] : void 0;
|
|
389
|
+
if (s)
|
|
390
|
+
return s;
|
|
391
|
+
const { full_path: n } = await d.generateStrategyEndpoint(t, e);
|
|
392
|
+
return i && (this.strategyUrlTemplates = {
|
|
393
|
+
...this.strategyUrlTemplates,
|
|
394
|
+
[i]: n
|
|
395
|
+
}), n;
|
|
396
|
+
},
|
|
397
|
+
/**
|
|
398
|
+
* Assigns a strategy to the current block. The config write is
|
|
399
|
+
* synchronous (before any await) so a block switch cannot misdirect
|
|
400
|
+
* it; the configVersion bump persists it to node config and triggers
|
|
401
|
+
* the product refetch via the coordinator control's subscription.
|
|
402
|
+
*/
|
|
403
|
+
assignStrategy(t) {
|
|
404
|
+
this.patchCurrentBlockConfig({
|
|
405
|
+
strategyId: String(t.strategy_id),
|
|
406
|
+
...t.size !== void 0 ? { size: String(t.size) } : {}
|
|
407
|
+
});
|
|
408
|
+
},
|
|
409
|
+
/**
|
|
410
|
+
* Clears the current block's strategy; it falls back to the per-block
|
|
411
|
+
* algorithm settings.
|
|
412
|
+
*
|
|
413
|
+
* `size` goes back to the default rather than staying on the removed
|
|
414
|
+
* strategy's count: with Number of Products hidden in RRS mode, a block
|
|
415
|
+
* left on that count would have no UI to correct it.
|
|
416
|
+
*/
|
|
417
|
+
removeStrategy() {
|
|
418
|
+
this.patchCurrentBlockConfig({ strategyId: "", size: U.size });
|
|
419
|
+
},
|
|
420
|
+
// ====================================================================
|
|
318
421
|
// Shared Data Fetching (fetched once, used by all blocks)
|
|
319
422
|
// ====================================================================
|
|
320
423
|
async fetchRecommendationCreateData() {
|
|
321
424
|
if (!this.activePredictiveAlgorithms.length) {
|
|
322
|
-
if (
|
|
323
|
-
await
|
|
425
|
+
if (f) {
|
|
426
|
+
await f;
|
|
324
427
|
return;
|
|
325
428
|
}
|
|
326
|
-
|
|
429
|
+
f = (async () => {
|
|
327
430
|
const {
|
|
328
431
|
activePredictiveAlgorithms: t,
|
|
329
432
|
languages: e,
|
|
330
433
|
currencies: r
|
|
331
|
-
} = await
|
|
434
|
+
} = await d.fetchRecommendationCreateData();
|
|
332
435
|
if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
|
|
333
|
-
const
|
|
334
|
-
|
|
436
|
+
const i = this.blockStates[this.currentRecommendationId];
|
|
437
|
+
i.filterStatus = !!i.recommendationConfigs.filters.length;
|
|
335
438
|
}
|
|
336
439
|
this.currencyList = r;
|
|
337
440
|
})();
|
|
338
441
|
try {
|
|
339
|
-
await
|
|
442
|
+
await f;
|
|
340
443
|
} finally {
|
|
341
|
-
|
|
444
|
+
f = null;
|
|
342
445
|
}
|
|
343
446
|
}
|
|
344
447
|
},
|
|
345
448
|
async fetchRecommendationFilters() {
|
|
346
449
|
if (!Object.keys(this.filterList).length) {
|
|
347
|
-
if (
|
|
348
|
-
await
|
|
450
|
+
if (g) {
|
|
451
|
+
await g;
|
|
349
452
|
return;
|
|
350
453
|
}
|
|
351
|
-
|
|
352
|
-
const t = await
|
|
454
|
+
g = (async () => {
|
|
455
|
+
const t = await d.fetchRecommendationFilters();
|
|
353
456
|
this.filterList = t;
|
|
354
457
|
})();
|
|
355
458
|
try {
|
|
356
|
-
await
|
|
459
|
+
await g;
|
|
357
460
|
} finally {
|
|
358
|
-
|
|
461
|
+
g = null;
|
|
359
462
|
}
|
|
360
463
|
}
|
|
361
464
|
},
|
|
@@ -370,59 +473,59 @@ const U = () => ({
|
|
|
370
473
|
deleteFilterGroup(t) {
|
|
371
474
|
if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
|
|
372
475
|
return;
|
|
373
|
-
const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.filter((
|
|
374
|
-
e.recommendationConfigs.filters = r.map((
|
|
375
|
-
...
|
|
376
|
-
filterGroup:
|
|
476
|
+
const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.filter((n) => n.filterGroup !== t), i = [...new Set(r.map((n) => n.filterGroup))].sort((n, o) => n - o), s = new Map(i.map((n, o) => [n, o + 1]));
|
|
477
|
+
e.recommendationConfigs.filters = r.map((n) => ({
|
|
478
|
+
...n,
|
|
479
|
+
filterGroup: s.get(n.filterGroup) ?? n.filterGroup
|
|
377
480
|
}));
|
|
378
481
|
},
|
|
379
482
|
updateFilter(t) {
|
|
380
483
|
if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
|
|
381
484
|
return;
|
|
382
|
-
const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.findIndex((
|
|
485
|
+
const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.findIndex((i) => i.filterNumber === t.filterNumber && i.filterGroup === t.filterGroup);
|
|
383
486
|
if (r !== -1) {
|
|
384
|
-
const
|
|
385
|
-
|
|
487
|
+
const i = [...e.recommendationConfigs.filters];
|
|
488
|
+
i[r] = {
|
|
386
489
|
...t,
|
|
387
|
-
isValid:
|
|
388
|
-
}, e.recommendationConfigs.filters =
|
|
490
|
+
isValid: A(t)
|
|
491
|
+
}, e.recommendationConfigs.filters = i;
|
|
389
492
|
}
|
|
390
493
|
},
|
|
391
494
|
deleteFilter(t) {
|
|
392
495
|
if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
|
|
393
496
|
return;
|
|
394
|
-
const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters].findIndex((
|
|
497
|
+
const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters].findIndex((i) => i.filterNumber === t.filterNumber && i.filterGroup === t.filterGroup);
|
|
395
498
|
if (r !== -1) {
|
|
396
|
-
let
|
|
397
|
-
if (
|
|
398
|
-
let
|
|
399
|
-
|
|
499
|
+
let i = [...e.recommendationConfigs.filters];
|
|
500
|
+
if (i.splice(r, 1), i.some((n) => n.filterGroup === t.filterGroup)) {
|
|
501
|
+
let n = 1;
|
|
502
|
+
i = i.map((o) => o.filterGroup === t.filterGroup ? { ...o, filterNumber: n++ } : o);
|
|
400
503
|
} else {
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
...
|
|
404
|
-
filterGroup: o.get(
|
|
504
|
+
const n = [...new Set(i.map((a) => a.filterGroup))].sort((a, c) => a - c), o = new Map(n.map((a, c) => [a, c + 1]));
|
|
505
|
+
i = i.map((a) => ({
|
|
506
|
+
...a,
|
|
507
|
+
filterGroup: o.get(a.filterGroup) ?? a.filterGroup
|
|
405
508
|
}));
|
|
406
509
|
}
|
|
407
|
-
e.recommendationConfigs.filters =
|
|
510
|
+
e.recommendationConfigs.filters = i;
|
|
408
511
|
}
|
|
409
512
|
},
|
|
410
513
|
addFilter(t) {
|
|
411
514
|
if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
|
|
412
515
|
return;
|
|
413
|
-
const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters],
|
|
516
|
+
const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters], s = r.filter(
|
|
414
517
|
(o) => o.filterGroup === t.filterGroup
|
|
415
|
-
).length + 1,
|
|
416
|
-
|
|
518
|
+
).length + 1, n = r.findLastIndex((o) => o.filterGroup === t.filterGroup);
|
|
519
|
+
n !== -1 ? r.splice(n + 1, 0, {
|
|
417
520
|
...t,
|
|
418
|
-
filterNumber:
|
|
521
|
+
filterNumber: s
|
|
419
522
|
}) : r.push({
|
|
420
523
|
...t,
|
|
421
|
-
filterNumber:
|
|
524
|
+
filterNumber: s
|
|
422
525
|
}), e.recommendationConfigs.filters = r;
|
|
423
526
|
},
|
|
424
527
|
generateFilterQuery() {
|
|
425
|
-
return
|
|
528
|
+
return I(this.recommendationConfigs.filters);
|
|
426
529
|
},
|
|
427
530
|
/**
|
|
428
531
|
* Validation-only check invoked at save-CTA time. Defined as an action
|
|
@@ -430,55 +533,93 @@ const U = () => ({
|
|
|
430
533
|
* every block's recommendationConfigs across user edits.
|
|
431
534
|
*/
|
|
432
535
|
hasInvalidBlock() {
|
|
433
|
-
return Object.values(this.blockStates).some((t) => !
|
|
536
|
+
return Object.values(this.blockStates).some((t) => !B(t.recommendationConfigs, this));
|
|
434
537
|
},
|
|
435
538
|
// ====================================================================
|
|
436
539
|
// Per-Block Product Fetching
|
|
437
540
|
// ====================================================================
|
|
438
541
|
async fetchRecommendationProducts() {
|
|
439
542
|
if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
|
|
440
|
-
if (
|
|
441
|
-
await
|
|
543
|
+
if (h) {
|
|
544
|
+
await h;
|
|
442
545
|
return;
|
|
443
546
|
}
|
|
444
|
-
|
|
547
|
+
h = this._doFetchProducts();
|
|
445
548
|
try {
|
|
446
|
-
await
|
|
549
|
+
await h;
|
|
447
550
|
} finally {
|
|
448
|
-
|
|
551
|
+
h = null;
|
|
449
552
|
}
|
|
450
553
|
}
|
|
451
554
|
},
|
|
452
555
|
async _doFetchProducts() {
|
|
453
556
|
var p;
|
|
454
|
-
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e,
|
|
557
|
+
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, i = P(), { isFeatureEnabled: s } = C();
|
|
558
|
+
if (s("reusableRecommendationStrategy") && r.strategyId) {
|
|
559
|
+
await this._doFetchStrategyProducts(t);
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
const n = r.filters.filter((u) => u.isValid), o = I(n), a = ((p = y().find((u) => u.key === r.strategy)) == null ? void 0 : p.path) || "", c = parseInt(r.size) || 6, l = {
|
|
455
563
|
locale: r.language,
|
|
456
564
|
currency: r.currencySettings.value,
|
|
457
|
-
partnerName:
|
|
565
|
+
partnerName: i.partnerName,
|
|
458
566
|
size: r.size,
|
|
459
567
|
details: !0,
|
|
460
|
-
campaignId:
|
|
568
|
+
campaignId: i.variationId
|
|
461
569
|
};
|
|
462
|
-
r.strategy === "manualMerchandising" ?
|
|
463
|
-
|
|
464
|
-
|
|
570
|
+
r.strategy === "manualMerchandising" ? l.productId = x(r.productIds) : r.strategy === "similarViewed" && (l.productId = "{itemId}"), r.strategy === "userBased" && (l.userId = "{user_id}"), o && (l.filter = o), r.shuffleProducts && (l.shuffle = !0), Object.assign(
|
|
571
|
+
l,
|
|
572
|
+
L(i.partnerName, r.strategy)
|
|
465
573
|
);
|
|
466
|
-
let
|
|
574
|
+
let m;
|
|
467
575
|
try {
|
|
468
|
-
|
|
576
|
+
m = await d.fetchRecommendationProducts(a, l);
|
|
469
577
|
} catch {
|
|
470
|
-
|
|
578
|
+
m = [];
|
|
471
579
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
580
|
+
this._setBlockProducts(t, m, c);
|
|
581
|
+
},
|
|
582
|
+
/**
|
|
583
|
+
* Fetches products for a strategy-backed block: listing lookup →
|
|
584
|
+
* endpoint-generate template → fill {locale}/{currency}, drop
|
|
585
|
+
* {user_id} (resolved at send time) → fetch. Any failure (dead
|
|
586
|
+
* strategy, resolution error) falls back to placeholder products.
|
|
587
|
+
*/
|
|
588
|
+
async _doFetchStrategyProducts(t) {
|
|
589
|
+
const { recommendationConfigs: e } = this.blockStates[t];
|
|
590
|
+
let r = [], i = parseInt(e.size) || 6;
|
|
591
|
+
try {
|
|
592
|
+
this.strategies.length || await this.fetchStrategies();
|
|
593
|
+
const s = this.strategies.find(
|
|
594
|
+
(n) => String(n.strategy_id) === e.strategyId
|
|
595
|
+
);
|
|
596
|
+
if (s) {
|
|
597
|
+
i = parseInt(String(s.size ?? "")) || i;
|
|
598
|
+
const n = e.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(s, n)).replaceAll("{locale}", e.language).replaceAll("{currency}", n), c = a.indexOf("?"), l = c === -1 ? a : a.slice(0, c), m = (c === -1 ? "" : a.slice(c + 1)).split("&").filter((u) => u && !u.startsWith("user_id=")), p = m.length ? `${l}?${m.join("&")}` : l;
|
|
599
|
+
r = await d.fetchRecommendationProductsByUrl(p);
|
|
600
|
+
}
|
|
601
|
+
} catch {
|
|
602
|
+
r = [];
|
|
478
603
|
}
|
|
604
|
+
this._setBlockProducts(t, r, i);
|
|
605
|
+
},
|
|
606
|
+
/**
|
|
607
|
+
* Writes products to a block's state, padded/clipped to exactly `size`:
|
|
608
|
+
* in-place content updates compare the DOM element count against
|
|
609
|
+
* products.length, and a longer list makes the renderer extend its slot
|
|
610
|
+
* grid, which resets migrator-applied styles.
|
|
611
|
+
*/
|
|
612
|
+
_setBlockProducts(t, e, r) {
|
|
613
|
+
if (!this.blockStates[t])
|
|
614
|
+
return;
|
|
615
|
+
const i = e.length > 0 ? e : b(r);
|
|
616
|
+
this.blockStates[t].recommendationProducts = [
|
|
617
|
+
...i.slice(0, r),
|
|
618
|
+
...b(Math.max(0, r - i.length))
|
|
619
|
+
];
|
|
479
620
|
}
|
|
480
621
|
}
|
|
481
622
|
});
|
|
482
623
|
export {
|
|
483
|
-
|
|
624
|
+
Y as useRecommendationExtensionStore
|
|
484
625
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ATTR_PRODUCT_PRICE as f, ATTR_PRODUCT_OLD_PRICE as O } from "../../constants/selectors.js";
|
|
2
2
|
import { DEFAULT_PRODUCTS_PER_ROW as w } from "../../constants/layout.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getDefaultProducts as A, DEFAULTS as g, createBlockTemplate as U, buildSpacer as h, DEFAULT_CARD_COMPOSITION as Y, buildElementRenderer as B, resolveInlinePriceOrder as F, buildCellOptions as I, DEFAULT_CARD_VISIBILITY as W } from "../utils.js";
|
|
4
4
|
import { DEFAULT_CELL_PADDING as k, renderInlineGridPriceCell as H, buildFillerCell as x, gridElementRenderer as y } from "./elementRenderer.js";
|
|
5
5
|
const G = `
|
|
6
6
|
<tr class="recommendation-product-row">
|
|
@@ -69,8 +69,8 @@ function M(t, r, o, e = {}, c = {}) {
|
|
|
69
69
|
);
|
|
70
70
|
}
|
|
71
71
|
function Q(t) {
|
|
72
|
-
const r = t ? `ins-recommendation-v3-block-${t}` : void 0, o =
|
|
73
|
-
return o.replace("{-{-TITLE-}-}",
|
|
72
|
+
const r = t ? `ins-recommendation-v3-block-${t}` : void 0, o = U("grid", r), e = A(), c = M(e, w);
|
|
73
|
+
return o.replace("{-{-TITLE-}-}", g.TITLE).replace("{-{-PRODUCT_ROWS-}-}", c).replace("{-{-MOBILE_PRODUCT_ROWS-}-}", "");
|
|
74
74
|
}
|
|
75
75
|
export {
|
|
76
76
|
Q as getDefaultTemplate,
|