@useinsider/guido 3.17.0 → 3.18.0-beta.19e1253

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.
Files changed (110) hide show
  1. package/README.md +6 -5
  2. package/dist/@types/config/schemas.js +7 -6
  3. package/dist/components/Guido.vue.js +10 -10
  4. package/dist/components/Guido.vue2.js +82 -76
  5. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +23 -0
  6. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +108 -0
  7. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue.js +17 -0
  8. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +57 -0
  9. package/dist/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue.js +19 -0
  10. package/dist/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue2.js +63 -0
  11. package/dist/composables/useCustomInterfaceAppearance.js +52 -38
  12. package/dist/composables/useModuleRepair.js +33 -0
  13. package/dist/composables/useRecommendation.js +41 -34
  14. package/dist/composables/useSave.js +30 -29
  15. package/dist/composables/useStripo.js +15 -15
  16. package/dist/composables/useSyncModuleExtractor.js +15 -13
  17. package/dist/composables/validators/useSyncModuleBlockValidator.js +24 -0
  18. package/dist/config/i18n/en/labels.json.js +1 -1
  19. package/dist/config/migrator/index.js +9 -8
  20. package/dist/config/migrator/recommendation/compositionMapper.js +20 -20
  21. package/dist/config/migrator/recommendation/extractors.js +29 -24
  22. package/dist/config/migrator/recommendation/htmlBuilder.js +116 -130
  23. package/dist/config/migrator/recommendation/settingsMapper.js +17 -17
  24. package/dist/config/migrator/recommendationMigrator.js +31 -25
  25. package/dist/config/migrator/recommendationTitleMigrator.js +119 -0
  26. package/dist/enums/academy.js +2 -1
  27. package/dist/enums/date.js +5 -3
  28. package/dist/enums/extensions/recommendationBlock.js +14 -11
  29. package/dist/extensions/Blocks/Items/block.js +118 -49
  30. package/dist/extensions/Blocks/Items/constants/currency.js +25 -0
  31. package/dist/extensions/Blocks/Items/controls/price/currencyLocation.js +25 -24
  32. package/dist/extensions/Blocks/Items/controls/price/currencySymbol.js +12 -11
  33. package/dist/extensions/Blocks/Items/template.js +153 -152
  34. package/dist/extensions/Blocks/Items/utils/constants.js +4 -0
  35. package/dist/extensions/Blocks/Recommendation/block.js +35 -29
  36. package/dist/extensions/Blocks/Recommendation/constants/blockIds.js +1 -1
  37. package/dist/extensions/Blocks/Recommendation/constants/controlIds.js +1 -1
  38. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +29 -27
  39. package/dist/extensions/Blocks/Recommendation/constants/selectors.js +35 -28
  40. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +309 -236
  41. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +241 -180
  42. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +123 -0
  43. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +1 -0
  44. package/dist/extensions/Blocks/Recommendation/controls/title/index.js +44 -0
  45. package/dist/extensions/Blocks/Recommendation/extension.js +31 -29
  46. package/dist/extensions/Blocks/Recommendation/services/configService.js +54 -36
  47. package/dist/extensions/Blocks/Recommendation/settingsPanel.js +23 -4
  48. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +203 -79
  49. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +3 -3
  50. package/dist/extensions/Blocks/Recommendation/templates/titleRows.js +33 -0
  51. package/dist/extensions/Blocks/Recommendation/templates/utils.js +85 -107
  52. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +22 -0
  53. package/dist/extensions/Blocks/Recommendation/utils/recommendationBlockCount.js +10 -6
  54. package/dist/extensions/Blocks/common-control.js +22 -19
  55. package/dist/guido.css +1 -1
  56. package/dist/services/recommendationApi.js +69 -30
  57. package/dist/src/@types/config/schemas.d.ts +2 -0
  58. package/dist/src/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.d.ts +3 -0
  59. package/dist/src/components/organisms/extensions/recommendation/RemoveStrategyModal.vue.d.ts +2 -0
  60. package/dist/src/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue.d.ts +15 -0
  61. package/dist/src/composables/useConfig.d.ts +2 -0
  62. package/dist/src/composables/useModuleRepair.d.ts +18 -0
  63. package/dist/src/composables/useRecommendation.d.ts +1 -0
  64. package/dist/src/composables/useSyncModuleExtractor.d.ts +2 -0
  65. package/dist/src/composables/validators/useSyncModuleBlockValidator.d.ts +3 -0
  66. package/dist/src/config/migrator/recommendation/extractors.d.ts +8 -0
  67. package/dist/src/config/migrator/recommendationTitleMigrator.d.ts +5 -0
  68. package/dist/src/enums/academy.d.ts +1 -0
  69. package/dist/src/enums/date.d.ts +1 -0
  70. package/dist/src/enums/extensions/recommendationBlock.d.ts +3 -0
  71. package/dist/src/extensions/Blocks/Items/block.d.ts +35 -0
  72. package/dist/src/extensions/Blocks/Items/constants/currency.d.ts +43 -0
  73. package/dist/src/extensions/Blocks/Items/utils/constants.d.ts +6 -0
  74. package/dist/src/extensions/Blocks/Recommendation/constants/blockIds.d.ts +2 -1
  75. package/dist/src/extensions/Blocks/Recommendation/constants/controlIds.d.ts +7 -0
  76. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +3 -6
  77. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +2 -2
  78. package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +12 -0
  79. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +11 -0
  80. package/dist/src/extensions/Blocks/Recommendation/controls/index.d.ts +1 -0
  81. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +44 -8
  82. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +16 -0
  83. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +1 -0
  84. package/dist/src/extensions/Blocks/Recommendation/controls/title/index.d.ts +86 -0
  85. package/dist/src/extensions/Blocks/Recommendation/services/configService.d.ts +12 -1
  86. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +194 -10
  87. package/dist/src/extensions/Blocks/Recommendation/templates/titleRows.d.ts +13 -0
  88. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +7 -0
  89. package/dist/src/extensions/Blocks/Recommendation/utils/nodeConfigWriter.d.ts +31 -0
  90. package/dist/src/extensions/Blocks/Recommendation/utils/recommendationBlockCount.d.ts +6 -2
  91. package/dist/src/extensions/Blocks/common-control.d.ts +4 -1
  92. package/dist/src/mock/api/recommendation-strategies.d.ts +2 -0
  93. package/dist/src/services/recommendationApi.d.ts +4 -1
  94. package/dist/src/stores/config.d.ts +18 -0
  95. package/dist/src/stores/save-as-template.d.ts +4 -3
  96. package/dist/src/utils/genericUtil.d.ts +5 -0
  97. package/dist/src/utils/itemsCurrencyRepair.d.ts +17 -0
  98. package/dist/static/assets/icons/line-change.svg.js +5 -0
  99. package/dist/static/assets/icons/line-delete.svg.js +5 -0
  100. package/dist/static/assets/icons/line-plus.svg.js +5 -0
  101. package/dist/static/styles/components/recommendation-strategy.css.js +152 -0
  102. package/dist/static/styles/customEditorStyle.css.js +3 -1
  103. package/dist/utils/dateUtil.js +23 -10
  104. package/dist/utils/genericUtil.js +28 -27
  105. package/dist/utils/itemsCurrencyRepair.js +39 -0
  106. package/dist/utils/pairProductVariables.js +58 -58
  107. package/dist/utils/templatePreparation.js +35 -34
  108. package/package.json +3 -2
  109. package/dist/composables/useModuleDynamicContentRepair.js +0 -37
  110. package/dist/src/composables/useModuleDynamicContentRepair.d.ts +0 -13
@@ -1,21 +1,31 @@
1
- import { getRecommendationFeedSourceMaps as g, getOperatorOptions as R, PriceAttributes as C } from "../../../../enums/extensions/recommendationBlock.js";
2
- import { useRecommendationApi as y } from "../../../../services/recommendationApi.js";
3
- import { useConfigStore as G } from "../../../../stores/config.js";
4
- import { defineStore as P } from "pinia";
1
+ import { getRecommendationFeedSourceMaps as R, URLS as D, getOperatorOptions as P, PriceAttributes as F } from "../../../../enums/extensions/recommendationBlock.js";
2
+ import { useRecommendationApi as _ } from "../../../../services/recommendationApi.js";
3
+ import { useConfigStore as L } from "../../../../stores/config.js";
4
+ import { asText as k } from "../../../../utils/genericUtil.js";
5
+ import { defineStore as N } from "pinia";
5
6
  import "../constants/selectors.js";
6
- import { DEFAULT_MOBILE_CARDS_IN_ROW as F, DEFAULT_CARDS_IN_ROW as D } from "../constants/layout.js";
7
- import { EXCLUDED_ALGORITHM_IDS as w } from "../constants/defaultConfig.js";
8
- import { getDefaultProducts as S } from "../templates/utils.js";
9
- import { generateCompleteFilterQuery as b } from "../utils/filterUtil.js";
10
- import { getPartnerRecommendationParams as v } from "../utils/partnerCustomizations.js";
11
- import { sanitizeProductIds as N } from "../utils/productIds.js";
12
- import { isFilterValid as x } from "../validation/filterSchema.js";
13
- import { isConfigValid as L } from "../validation/requiredFields.js";
14
- const h = y();
15
- let m = null, u = null, d = null;
16
- function k() {
7
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as U, DEFAULT_CARDS_IN_ROW as A } from "../constants/layout.js";
8
+ import { DEFAULT_NODE_CONFIG as E, EXCLUDED_ALGORITHM_IDS as x } from "../constants/defaultConfig.js";
9
+ import { getDefaultProducts as C } from "../templates/utils.js";
10
+ import { generateCompleteFilterQuery as w } from "../utils/filterUtil.js";
11
+ import { getPartnerRecommendationParams as M } from "../utils/partnerCustomizations.js";
12
+ import { sanitizeProductIds as T } from "../utils/productIds.js";
13
+ import { isFilterValid as B } from "../validation/filterSchema.js";
14
+ import { isConfigValid as O } from "../validation/requiredFields.js";
15
+ const d = _();
16
+ let h = null, g = null, S = null, p = null;
17
+ const y = /* @__PURE__ */ new Map();
18
+ let u = null;
19
+ const z = (t, e) => {
20
+ const r = t.filter((s) => !e.has(String(s.strategy_id)));
21
+ if (!r.length)
22
+ return null;
23
+ const n = r.reduce((s, i) => k(i.created_at) > k(s.created_at) ? i : s);
24
+ return String(n.strategy_id);
25
+ };
26
+ function G() {
17
27
  return {
18
- cardsInRow: D,
28
+ cardsInRow: A,
19
29
  currencySettings: {
20
30
  name: "USD",
21
31
  value: "USD",
@@ -29,13 +39,14 @@ function k() {
29
39
  productIds: [],
30
40
  id: 1,
31
41
  language: "en_US",
32
- mobileCardsInRow: F,
42
+ mobileCardsInRow: U,
33
43
  mobileLayoutEnabled: !1,
34
44
  orientation: "grid",
35
45
  recommendedProducts: [],
36
46
  sendProductRequestFlag: !1,
37
47
  shuffleProducts: !1,
38
48
  strategy: "mostPopular",
49
+ strategyId: "",
39
50
  textTrimming: !0,
40
51
  unresponsive: !1,
41
52
  size: "6",
@@ -44,28 +55,34 @@ function k() {
44
55
  priceHideIfSameAsDiscounted: !1
45
56
  };
46
57
  }
47
- function I() {
58
+ function v() {
48
59
  return {
49
- recommendationConfigs: k(),
60
+ recommendationConfigs: G(),
50
61
  recommendationProducts: [],
51
62
  filterStatus: !1,
52
63
  filterSelectionDrawerStatus: !1,
64
+ assignStrategyDrawerStatus: !1,
65
+ removeStrategyModalStatus: !1,
53
66
  filterGroup: 1,
54
67
  isInitialized: !1,
55
68
  filterSnapshot: null
56
69
  };
57
70
  }
58
- const U = () => ({
71
+ const V = () => ({
59
72
  recommendationCampaignUrls: {},
60
73
  activePredictiveAlgorithms: [],
61
74
  languages: {},
62
75
  currencyList: [],
63
76
  filterList: {},
77
+ strategies: [],
78
+ strategiesLoading: !1,
79
+ strategyUrlTemplates: {},
80
+ lastCreatedStrategyId: null,
64
81
  blockStates: {},
65
82
  currentRecommendationId: null,
66
83
  configVersion: 0
67
- }), H = P("guidoRecommendationExtension", {
68
- state: () => U(),
84
+ }), nt = N("guidoRecommendationExtension", {
85
+ state: () => V(),
69
86
  getters: {
70
87
  // ====================================================================
71
88
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -75,7 +92,7 @@ const U = () => ({
75
92
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
76
93
  */
77
94
  recommendationConfigs(t) {
78
- return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : k();
95
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : G();
79
96
  },
80
97
  /**
81
98
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
@@ -89,6 +106,16 @@ const U = () => ({
89
106
  filterSelectionDrawerStatus(t) {
90
107
  return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].filterSelectionDrawerStatus : !1;
91
108
  },
109
+ assignStrategyDrawerStatus(t) {
110
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].assignStrategyDrawerStatus : !1;
111
+ },
112
+ removeStrategyModalStatus(t) {
113
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].removeStrategyModalStatus : !1;
114
+ },
115
+ assignedStrategy(t) {
116
+ const { strategyId: e } = this.recommendationConfigs;
117
+ return e ? t.strategies.find((r) => String(r.strategy_id) === e) ?? null : null;
118
+ },
92
119
  /**
93
120
  * Proxy getter: delegates to blockStates[currentRecommendationId].filterStatus
94
121
  */
@@ -120,9 +147,9 @@ const U = () => ({
120
147
  return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
121
148
  },
122
149
  getActivePredictiveAlgorithms: (t) => {
123
- const e = g(), r = [];
124
- return t.activePredictiveAlgorithms.filter((n) => !w.includes(n)).forEach((n) => {
125
- r.push(...e.filter((c) => c.id === n));
150
+ const e = R(), r = [];
151
+ return t.activePredictiveAlgorithms.filter((n) => !x.includes(n)).forEach((n) => {
152
+ r.push(...e.filter((s) => s.id === n));
126
153
  }), r.map((n) => ({
127
154
  text: n.name,
128
155
  value: n.key
@@ -139,7 +166,7 @@ const U = () => ({
139
166
  getFilterList() {
140
167
  return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
141
168
  let e;
142
- return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : C.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
169
+ return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : F.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
143
170
  text: t.displayName,
144
171
  value: e,
145
172
  type: t.attributeType
@@ -161,7 +188,7 @@ const U = () => ({
161
188
  setCurrentBlock(t) {
162
189
  this.blockStates[t] || (this.blockStates = {
163
190
  ...this.blockStates,
164
- [t]: I()
191
+ [t]: v()
165
192
  }), this.currentRecommendationId = t;
166
193
  },
167
194
  /**
@@ -193,10 +220,10 @@ const U = () => ({
193
220
  [e]: o
194
221
  };
195
222
  }
196
- const n = t.toString(), c = e.toString(), i = this.recommendationCampaignUrls[n];
223
+ const n = t.toString(), s = e.toString(), i = this.recommendationCampaignUrls[n];
197
224
  i && (this.recommendationCampaignUrls = {
198
225
  ...this.recommendationCampaignUrls,
199
- [c]: i
226
+ [s]: i
200
227
  });
201
228
  },
202
229
  /**
@@ -221,7 +248,7 @@ const U = () => ({
221
248
  * `isInitialized`) alone.
222
249
  */
223
250
  seedBlockUrlConfig(t, e) {
224
- const r = (o, s) => o === "." || o === "," || o === " " ? o : s, n = {
251
+ const r = (o, c) => o === "." || o === "," || o === " " ? o : c, n = {
225
252
  name: e.currencyCode,
226
253
  value: e.currencyCode,
227
254
  symbol: e.currencyCode,
@@ -229,17 +256,18 @@ const U = () => ({
229
256
  decimalCount: String(e.currencyDecimalCount),
230
257
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
231
258
  thousandSeparator: r(e.currencyThousandSeparator, ".")
232
- }, c = !this.blockStates[t], i = c ? I() : this.blockStates[t];
259
+ }, s = !this.blockStates[t], i = s ? v() : this.blockStates[t];
233
260
  i.recommendationConfigs = {
234
261
  ...i.recommendationConfigs,
235
262
  strategy: e.strategy,
263
+ strategyId: e.strategyId,
236
264
  language: e.language,
237
265
  size: e.size,
238
266
  productIds: e.productIds,
239
267
  filters: e.filters,
240
268
  shuffleProducts: e.shuffleProducts,
241
269
  currencySettings: n
242
- }, c && (this.blockStates = {
270
+ }, s && (this.blockStates = {
243
271
  ...this.blockStates,
244
272
  [t]: i
245
273
  });
@@ -267,7 +295,7 @@ const U = () => ({
267
295
  * Creates a filter with the first available attribute and operator pre-selected.
268
296
  */
269
297
  createDefaultFilter(t, e) {
270
- const [r] = this.getFilterList, [n] = R(r == null ? void 0 : r.type);
298
+ const [r] = this.getFilterList, [n] = P(r == null ? void 0 : r.type);
271
299
  return {
272
300
  type: "standardFilter",
273
301
  attribute: (r == null ? void 0 : r.value) ?? "",
@@ -314,21 +342,89 @@ const U = () => ({
314
342
  const t = this.blockStates[this.currentRecommendationId];
315
343
  t.filterSnapshot !== null && (t.recommendationConfigs.filters = t.filterSnapshot, t.filterSnapshot = null), t.filterSelectionDrawerStatus = !1;
316
344
  },
345
+ openAssignStrategyDrawer() {
346
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !0);
347
+ },
348
+ closeAssignStrategyDrawer() {
349
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].assignStrategyDrawerStatus = !1);
350
+ },
351
+ openRemoveStrategyModal() {
352
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !0);
353
+ },
354
+ closeRemoveStrategyModal() {
355
+ this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !1);
356
+ },
357
+ async fetchStrategies() {
358
+ if (p) {
359
+ await p;
360
+ return;
361
+ }
362
+ p = (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 p;
372
+ } finally {
373
+ p = null;
374
+ }
375
+ },
376
+ /**
377
+ * Opens Smart Recommender's strategy creation page in a new tab. The first time the user
378
+ * comes back, the list is fetched once more and any strategy that appeared meanwhile
379
+ * is remembered so the drawer can preselect it.
380
+ */
381
+ openStrategyCreation() {
382
+ const t = new Set(this.strategies.map((r) => String(r.strategy_id)));
383
+ window.open(D.RECOMMENDATION_STRATEGY_CREATE_PATH, "_blank", "noopener"), u == null || u();
384
+ const e = () => {
385
+ document.hidden || (u == null || u(), this.fetchStrategies().then(() => {
386
+ this.lastCreatedStrategyId = z(this.strategies, t);
387
+ }).catch(() => {
388
+ }));
389
+ };
390
+ document.addEventListener("visibilitychange", e), window.addEventListener("focus", e), u = () => {
391
+ document.removeEventListener("visibilitychange", e), window.removeEventListener("focus", e), u = null;
392
+ };
393
+ },
394
+ async resolveStrategyUrlTemplate(t, e) {
395
+ const r = typeof t.updated_at == "string" ? t.updated_at : "", n = r ? `${t.strategy_id}:${r}:${e}` : "", s = n ? this.strategyUrlTemplates[n] : void 0;
396
+ if (s)
397
+ return s;
398
+ const { full_path: i = "" } = await d.generateStrategyEndpoint(t, e) ?? {};
399
+ return n && i && (this.strategyUrlTemplates = {
400
+ ...this.strategyUrlTemplates,
401
+ [n]: i
402
+ }), i;
403
+ },
404
+ assignStrategy(t) {
405
+ this.patchCurrentBlockConfig({
406
+ strategyId: String(t.strategy_id),
407
+ ...t.size !== void 0 ? { size: String(t.size) } : {}
408
+ });
409
+ },
410
+ removeStrategy() {
411
+ this.patchCurrentBlockConfig({ strategyId: "", size: E.size });
412
+ },
317
413
  // ====================================================================
318
414
  // Shared Data Fetching (fetched once, used by all blocks)
319
415
  // ====================================================================
320
416
  async fetchRecommendationCreateData() {
321
417
  if (!this.activePredictiveAlgorithms.length) {
322
- if (m) {
323
- await m;
418
+ if (h) {
419
+ await h;
324
420
  return;
325
421
  }
326
- m = (async () => {
422
+ h = (async () => {
327
423
  const {
328
424
  activePredictiveAlgorithms: t,
329
425
  languages: e,
330
426
  currencies: r
331
- } = await h.fetchRecommendationCreateData();
427
+ } = await d.fetchRecommendationCreateData();
332
428
  if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
333
429
  const n = this.blockStates[this.currentRecommendationId];
334
430
  n.filterStatus = !!n.recommendationConfigs.filters.length;
@@ -336,26 +432,26 @@ const U = () => ({
336
432
  this.currencyList = r;
337
433
  })();
338
434
  try {
339
- await m;
435
+ await h;
340
436
  } finally {
341
- m = null;
437
+ h = null;
342
438
  }
343
439
  }
344
440
  },
345
441
  async fetchRecommendationFilters() {
346
442
  if (!Object.keys(this.filterList).length) {
347
- if (u) {
348
- await u;
443
+ if (g) {
444
+ await g;
349
445
  return;
350
446
  }
351
- u = (async () => {
352
- const t = await h.fetchRecommendationFilters();
447
+ g = (async () => {
448
+ const t = await d.fetchRecommendationFilters();
353
449
  this.filterList = t;
354
450
  })();
355
451
  try {
356
- await u;
452
+ await g;
357
453
  } finally {
358
- u = null;
454
+ g = null;
359
455
  }
360
456
  }
361
457
  },
@@ -370,10 +466,10 @@ const U = () => ({
370
466
  deleteFilterGroup(t) {
371
467
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
372
468
  return;
373
- const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.filter((i) => i.filterGroup !== t), n = [...new Set(r.map((i) => i.filterGroup))].sort((i, o) => i - o), c = new Map(n.map((i, o) => [i, o + 1]));
469
+ const e = this.blockStates[this.currentRecommendationId], r = e.recommendationConfigs.filters.filter((i) => i.filterGroup !== t), n = [...new Set(r.map((i) => i.filterGroup))].sort((i, o) => i - o), s = new Map(n.map((i, o) => [i, o + 1]));
374
470
  e.recommendationConfigs.filters = r.map((i) => ({
375
471
  ...i,
376
- filterGroup: c.get(i.filterGroup) ?? i.filterGroup
472
+ filterGroup: s.get(i.filterGroup) ?? i.filterGroup
377
473
  }));
378
474
  },
379
475
  updateFilter(t) {
@@ -384,7 +480,7 @@ const U = () => ({
384
480
  const n = [...e.recommendationConfigs.filters];
385
481
  n[r] = {
386
482
  ...t,
387
- isValid: x(t)
483
+ isValid: B(t)
388
484
  }, e.recommendationConfigs.filters = n;
389
485
  }
390
486
  },
@@ -398,10 +494,10 @@ const U = () => ({
398
494
  let i = 1;
399
495
  n = n.map((o) => o.filterGroup === t.filterGroup ? { ...o, filterNumber: i++ } : o);
400
496
  } else {
401
- const i = [...new Set(n.map((s) => s.filterGroup))].sort((s, a) => s - a), o = new Map(i.map((s, a) => [s, a + 1]));
402
- n = n.map((s) => ({
403
- ...s,
404
- filterGroup: o.get(s.filterGroup) ?? s.filterGroup
497
+ const i = [...new Set(n.map((c) => c.filterGroup))].sort((c, a) => c - a), o = new Map(i.map((c, a) => [c, a + 1]));
498
+ n = n.map((c) => ({
499
+ ...c,
500
+ filterGroup: o.get(c.filterGroup) ?? c.filterGroup
405
501
  }));
406
502
  }
407
503
  e.recommendationConfigs.filters = n;
@@ -410,19 +506,19 @@ const U = () => ({
410
506
  addFilter(t) {
411
507
  if (this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])
412
508
  return;
413
- const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters], c = r.filter(
509
+ const e = this.blockStates[this.currentRecommendationId], r = [...e.recommendationConfigs.filters], s = r.filter(
414
510
  (o) => o.filterGroup === t.filterGroup
415
511
  ).length + 1, i = r.findLastIndex((o) => o.filterGroup === t.filterGroup);
416
512
  i !== -1 ? r.splice(i + 1, 0, {
417
513
  ...t,
418
- filterNumber: c
514
+ filterNumber: s
419
515
  }) : r.push({
420
516
  ...t,
421
- filterNumber: c
517
+ filterNumber: s
422
518
  }), e.recommendationConfigs.filters = r;
423
519
  },
424
520
  generateFilterQuery() {
425
- return b(this.recommendationConfigs.filters);
521
+ return w(this.recommendationConfigs.filters);
426
522
  },
427
523
  /**
428
524
  * Validation-only check invoked at save-CTA time. Defined as an action
@@ -430,55 +526,83 @@ const U = () => ({
430
526
  * every block's recommendationConfigs across user edits.
431
527
  */
432
528
  hasInvalidBlock() {
433
- return Object.values(this.blockStates).some((t) => !L(t.recommendationConfigs, this));
529
+ return Object.values(this.blockStates).some((t) => !O(t.recommendationConfigs, this));
434
530
  },
435
531
  // ====================================================================
436
532
  // Per-Block Product Fetching
437
533
  // ====================================================================
438
534
  async fetchRecommendationProducts() {
439
535
  if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
440
- if (d) {
441
- await d;
536
+ if (S) {
537
+ await S;
442
538
  return;
443
539
  }
444
- d = this._doFetchProducts();
540
+ S = this._doFetchProducts();
445
541
  try {
446
- await d;
542
+ await S;
447
543
  } finally {
448
- d = null;
544
+ S = null;
449
545
  }
450
546
  }
451
547
  },
452
548
  async _doFetchProducts() {
453
- var p;
454
- const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = r.filters.filter((l) => l.isValid), c = b(n), i = ((p = g().find((l) => l.key === r.strategy)) == null ? void 0 : p.path) || "", o = G(), s = parseInt(r.size) || 6, a = {
549
+ var f;
550
+ const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = L();
551
+ if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
552
+ await this._doFetchStrategyProducts(t);
553
+ return;
554
+ }
555
+ const s = r.filters.filter((m) => m.isValid), i = w(s), o = ((f = R().find((m) => m.key === r.strategy)) == null ? void 0 : f.path) || "", c = parseInt(r.size) || 6, a = {
455
556
  locale: r.language,
456
557
  currency: r.currencySettings.value,
457
- partnerName: o.partnerName,
558
+ partnerName: n.partnerName,
458
559
  size: r.size,
459
560
  details: !0,
460
- campaignId: o.variationId
561
+ campaignId: n.variationId
461
562
  };
462
- r.strategy === "manualMerchandising" ? a.productId = N(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), c && (a.filter = c), r.shuffleProducts && (a.shuffle = !0), Object.assign(
563
+ r.strategy === "manualMerchandising" ? a.productId = T(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), i && (a.filter = i), r.shuffleProducts && (a.shuffle = !0), Object.assign(
463
564
  a,
464
- v(o.partnerName, r.strategy)
565
+ M(n.partnerName, r.strategy)
465
566
  );
466
- let f;
567
+ let l;
467
568
  try {
468
- f = await h.fetchRecommendationProducts(i, a);
569
+ l = await d.fetchRecommendationProducts(o, a);
469
570
  } catch {
470
- f = [];
571
+ l = [];
471
572
  }
472
- if (this.blockStates[t]) {
473
- const l = f.length > 0 ? f : S(s);
474
- l.length < s ? this.blockStates[t].recommendationProducts = [
475
- ...l,
476
- ...S(s - l.length)
477
- ] : l.length > s ? this.blockStates[t].recommendationProducts = l.slice(0, s) : this.blockStates[t].recommendationProducts = l;
573
+ this._setBlockProducts(t, l, c);
574
+ },
575
+ async _doFetchStrategyProducts(t) {
576
+ const e = (y.get(t) ?? 0) + 1;
577
+ y.set(t, e);
578
+ const { recommendationConfigs: r } = this.blockStates[t];
579
+ let n = [], s = parseInt(r.size) || 6;
580
+ try {
581
+ await this.fetchStrategies();
582
+ const i = this.strategies.find(
583
+ (o) => String(o.strategy_id) === r.strategyId
584
+ );
585
+ if (i) {
586
+ s = parseInt(String(i.size ?? "")) || s;
587
+ 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((b) => b && !b.startsWith("user_id=")), I = m.length ? `${f}?${m.join("&")}` : f;
588
+ I && (n = await d.fetchRecommendationProductsByUrl(I));
589
+ }
590
+ } catch {
591
+ n = [];
478
592
  }
593
+ y.get(t) === e && this._setBlockProducts(t, n, s);
594
+ },
595
+ _setBlockProducts(t, e, r) {
596
+ if (!this.blockStates[t])
597
+ return;
598
+ const n = e.length > 0 ? e : C(r);
599
+ this.blockStates[t].recommendationProducts = [
600
+ ...n.slice(0, r),
601
+ ...C(Math.max(0, r - n.length))
602
+ ];
479
603
  }
480
604
  }
481
605
  });
482
606
  export {
483
- H as useRecommendationExtensionStore
607
+ nt as useRecommendationExtensionStore
484
608
  };
@@ -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 { 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";
3
+ import { createBlockTemplate as A, getDefaultProducts as g, DEFAULTS 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 = U("grid", r), e = A(), c = M(e, w);
73
- return o.replace("{-{-TITLE-}-}", g.TITLE).replace("{-{-PRODUCT_ROWS-}-}", c).replace("{-{-MOBILE_PRODUCT_ROWS-}-}", "");
72
+ const r = t ? `ins-recommendation-v3-block-${t}` : void 0, o = A("grid", r), e = g(), c = M(e, w);
73
+ return o.replace("{-{-TITLE-}-}", U.TITLE).replace("{-{-PRODUCT_ROWS-}-}", c).replace("{-{-MOBILE_PRODUCT_ROWS-}-}", "");
74
74
  }
75
75
  export {
76
76
  Q as getDefaultTemplate,
@@ -0,0 +1,33 @@
1
+ import { RecommendationBlockId as r } from "../constants/blockIds.js";
2
+ import { DEFAULT_ROW_SPACING as l } from "../constants/layout.js";
3
+ import { CSS_CLASS_ATTRIBUTE_ROW as d, ATTR_RECOMMENDATION_TITLE as n, ATTR_DATA_VISIBILITY as A, CSS_CLASS_TITLE_CELL as _, CSS_CLASS_SPACER as c } from "../constants/selectors.js";
4
+ const a = "You May Also Like!", i = '<p style="font-size: 28px; color: #333333;"><strong>{-{-TITLE-}-}</strong></p>';
5
+ function E(s = i, t = !0, T = l) {
6
+ const e = `class="${d}" data-attribute-type="${n}" ${A}="${t ? "1" : "0"}"`, o = t ? "" : ' style="display: none;"';
7
+ return `
8
+ <tr ${e}${o}>
9
+ <td>
10
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
11
+ <tbody>
12
+ <tr>
13
+ <td
14
+ class="esd-block-text ${_} es-p10t es-p10b es-p20l es-p20r"
15
+ align="center"
16
+ esd-extension-block-id="${r.TITLE}">
17
+ ${s}
18
+ </td>
19
+ </tr>
20
+ </tbody>
21
+ </table>
22
+ </td>
23
+ </tr>
24
+ <tr ${e}${o}>
25
+ <td class="${c}" style="height: ${T}px;"></td>
26
+ </tr>
27
+ `;
28
+ }
29
+ export {
30
+ i as DEFAULT_TITLE_PARAGRAPH,
31
+ a as DEFAULT_TITLE_TEXT,
32
+ E as buildTitleRows
33
+ };