@useinsider/guido 3.17.0-beta.ec8eabb → 3.17.0-beta.edf4165

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 (61) hide show
  1. package/README.md +1 -0
  2. package/dist/@types/config/schemas.js +7 -6
  3. package/dist/components/Guido.vue.js +8 -8
  4. package/dist/components/Guido.vue2.js +100 -97
  5. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +21 -0
  6. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +106 -0
  7. package/dist/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue.js +19 -0
  8. package/dist/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue2.js +63 -0
  9. package/dist/components/organisms/header/EditorActions.vue.js +1 -1
  10. package/dist/components/organisms/header/EditorActions.vue2.js +36 -44
  11. package/dist/composables/useActionsApi.js +67 -82
  12. package/dist/composables/useAutoSave.js +26 -31
  13. package/dist/composables/useCustomInterfaceAppearance.js +52 -38
  14. package/dist/composables/useGuidoStateBridge.js +30 -31
  15. package/dist/composables/useRecommendation.js +41 -34
  16. package/dist/composables/useSave.js +36 -40
  17. package/dist/config/migrator/recommendation/settingsMapper.js +17 -17
  18. package/dist/config/migrator/recommendationMigrator.js +5 -4
  19. package/dist/enums/academy.js +2 -1
  20. package/dist/enums/date.js +5 -3
  21. package/dist/enums/extensions/recommendationBlock.js +3 -1
  22. package/dist/extensions/Blocks/Recommendation/block.js +26 -21
  23. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +34 -34
  24. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +96 -95
  25. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +162 -166
  26. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +124 -0
  27. package/dist/extensions/Blocks/Recommendation/services/configService.js +35 -35
  28. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +165 -79
  29. package/dist/extensions/Blocks/common-control.js +22 -19
  30. package/dist/guido.css +1 -1
  31. package/dist/services/recommendationApi.js +69 -30
  32. package/dist/src/@types/config/schemas.d.ts +2 -0
  33. package/dist/src/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.d.ts +3 -0
  34. package/dist/src/components/organisms/extensions/recommendation/StrategyInfoBoxContent.vue.d.ts +15 -0
  35. package/dist/src/composables/useConfig.d.ts +2 -0
  36. package/dist/src/composables/useRecommendation.d.ts +1 -0
  37. package/dist/src/enums/academy.d.ts +1 -0
  38. package/dist/src/enums/date.d.ts +1 -0
  39. package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
  40. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +2 -6
  41. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  42. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +10 -4
  43. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +16 -0
  44. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +150 -10
  45. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +1 -0
  46. package/dist/src/extensions/Blocks/common-control.d.ts +4 -1
  47. package/dist/src/mock/api/recommendation-strategies.d.ts +2 -0
  48. package/dist/src/services/recommendationApi.d.ts +4 -1
  49. package/dist/src/stores/config.d.ts +18 -0
  50. package/dist/src/stores/save-as-template.d.ts +4 -3
  51. package/dist/src/utils/genericUtil.d.ts +5 -0
  52. package/dist/static/assets/icons/line-change.svg.js +5 -0
  53. package/dist/static/assets/icons/line-delete.svg.js +5 -0
  54. package/dist/static/assets/icons/line-plus.svg.js +5 -0
  55. package/dist/static/styles/components/recommendation-strategy.css.js +155 -0
  56. package/dist/utils/dateUtil.js +23 -10
  57. package/dist/utils/genericUtil.js +28 -27
  58. package/dist/utils/templatePreparation.js +35 -34
  59. package/package.json +2 -1
  60. package/dist/composables/useEditorLock.js +0 -18
  61. package/dist/src/composables/useEditorLock.d.ts +0 -11
@@ -1,53 +1,58 @@
1
- var f = Object.defineProperty;
2
- var p = (d, l, t) => l in d ? f(d, l, { enumerable: !0, configurable: !0, writable: !0, value: t }) : d[l] = t;
3
- var s = (d, l, t) => p(d, typeof l != "symbol" ? l + "" : l, t);
4
- import { CommonControl as g } from "../../../common-control.js";
5
- import { DEFAULT_NODE_CONFIG as c } from "../../constants/defaultConfig.js";
6
- import { RecommendationConfigService as h } from "../../services/configService.js";
7
- import { useRecommendationExtensionStore as y } from "../../store/recommendation.js";
8
- import { AlgorithmControl as N } from "./algorithm.js";
9
- import { ALGORITHM_CONTROL_ID as tt } from "./algorithm.js";
1
+ var C = Object.defineProperty;
2
+ var g = (d, c, t) => c in d ? C(d, c, { enumerable: !0, configurable: !0, writable: !0, value: t }) : d[c] = t;
3
+ var n = (d, c, t) => g(d, typeof c != "symbol" ? c + "" : c, t);
4
+ import { useConfig as p } from "../../../../../composables/useConfig.js";
5
+ import { CommonControl as y } from "../../../common-control.js";
6
+ import { CURRENT_CONFIG_VERSION as _, DEFAULT_NODE_CONFIG as a } from "../../constants/defaultConfig.js";
7
+ import { RecommendationConfigService as m } from "../../services/configService.js";
8
+ import { useRecommendationExtensionStore as N } from "../../store/recommendation.js";
9
+ import { AlgorithmControl as I } from "./algorithm.js";
10
+ import { ALGORITHM_CONTROL_ID as it } from "./algorithm.js";
10
11
  import { CurrencyControl as R } from "./currency.js";
11
- import { CURRENCY_CONTROL_ID as ot } from "./currency.js";
12
- import { FiltersControl as I } from "./filters.js";
13
- import { FILTERS_CONTROL_ID as nt } from "./filters.js";
14
- import { LayoutOrientationControl as _ } from "./layoutOrientation.js";
15
- import { LAYOUT_ORIENTATION_CONTROL_ID as st } from "./layoutOrientation.js";
16
- import { LocaleControl as b } from "./locale.js";
17
- import { LOCALE_CONTROL_ID as lt } from "./locale.js";
18
- import { PricePlacementControl as T } from "./pricePlacement.js";
19
- import { PRICE_PLACEMENT_CONTROL_ID as ut } from "./pricePlacement.js";
20
- import { ProductCountControl as O } from "./productCount.js";
21
- import { PRODUCT_COUNT_CONTROL_ID as ht } from "./productCount.js";
22
- import { ProductLayoutControl as P } from "./productLayout.js";
23
- import { PRODUCT_LAYOUT_CONTROL_ID as Ct } from "./productLayout.js";
24
- import { ShuffleControl as S } from "./shuffle.js";
25
- import { SHUFFLE_CONTROL_ID as pt } from "./shuffle.js";
26
- import { setCurrencyAttributes as L, getBlockElement as k, isPartnerManagedBlock as D, updateProductContentInPlace as E, regenerateProductRowsWithStyles as A } from "./utils.js";
27
- import { adjustProductsToSize as yt, formatProductPrice as Nt, getCardComposition as Rt, getCurrentLayout as It, regenerateMobileProductRows as _t, updatePricesInPlace as bt, updateSingleProductContent as Tt } from "./utils.js";
28
- import { useDebounceFn as m } from "../../../../../node_modules/@vueuse/shared/index.js";
29
- const v = "recommendation-id", w = "ui-elements-recommendation-block";
30
- class Q extends g {
12
+ import { CURRENCY_CONTROL_ID as at } from "./currency.js";
13
+ import { FiltersControl as b } from "./filters.js";
14
+ import { FILTERS_CONTROL_ID as lt } from "./filters.js";
15
+ import { LayoutOrientationControl as T } from "./layoutOrientation.js";
16
+ import { LAYOUT_ORIENTATION_CONTROL_ID as dt } from "./layoutOrientation.js";
17
+ import { LocaleControl as S } from "./locale.js";
18
+ import { LOCALE_CONTROL_ID as ht } from "./locale.js";
19
+ import { PricePlacementControl as O } from "./pricePlacement.js";
20
+ import { PRICE_PLACEMENT_CONTROL_ID as Ct } from "./pricePlacement.js";
21
+ import { ProductCountControl as P } from "./productCount.js";
22
+ import { PRODUCT_COUNT_CONTROL_ID as pt } from "./productCount.js";
23
+ import { ProductLayoutControl as L } from "./productLayout.js";
24
+ import { PRODUCT_LAYOUT_CONTROL_ID as _t } from "./productLayout.js";
25
+ import { ShuffleControl as k } from "./shuffle.js";
26
+ import { SHUFFLE_CONTROL_ID as It } from "./shuffle.js";
27
+ import { StrategyControl as E } from "./strategy.js";
28
+ import { STRATEGY_CONTROL_ID as bt } from "./strategy.js";
29
+ import { setCurrencyAttributes as D, getBlockElement as B, isPartnerManagedBlock as w, updateProductContentInPlace as A, regenerateProductRowsWithStyles as v } from "./utils.js";
30
+ import { adjustProductsToSize as St, formatProductPrice as Ot, getCardComposition as Pt, getCurrentLayout as Lt, regenerateMobileProductRows as kt, updatePricesInPlace as Et, updateSingleProductContent as Dt } from "./utils.js";
31
+ import { useDebounceFn as h } from "../../../../../node_modules/@vueuse/shared/index.js";
32
+ const x = "recommendation-id", F = "ui-elements-recommendation-block";
33
+ class ot extends y {
31
34
  constructor() {
32
35
  super(...arguments);
33
- s(this, "store", y());
34
- s(this, "storeUnsubscription", () => {
36
+ n(this, "store", N());
37
+ n(this, "storeUnsubscription", () => {
35
38
  });
36
- s(this, "syncedBlockIds", /* @__PURE__ */ new Set());
39
+ n(this, "syncedBlockIds", /* @__PURE__ */ new Set());
37
40
  // Sub-control instances for lifecycle management
38
- s(this, "algorithmControl", null);
39
- s(this, "localeControl", null);
40
- s(this, "currencyControl", null);
41
- s(this, "productCountControl", null);
42
- s(this, "productLayoutControl", null);
43
- s(this, "filtersControl", null);
44
- s(this, "shuffleControl", null);
45
- s(this, "pricePlacementControl", null);
46
- s(this, "layoutOrientationControl", null);
41
+ n(this, "algorithmControl", null);
42
+ n(this, "localeControl", null);
43
+ n(this, "currencyControl", null);
44
+ n(this, "productCountControl", null);
45
+ n(this, "productLayoutControl", null);
46
+ n(this, "filtersControl", null);
47
+ n(this, "shuffleControl", null);
48
+ n(this, "pricePlacementControl", null);
49
+ n(this, "layoutOrientationControl", null);
50
+ n(this, "strategyControl", null);
51
+ n(this, "rrsEnabled", !1);
47
52
  /**
48
53
  * Debounced product fetch to prevent rapid API calls during config changes
49
54
  */
50
- s(this, "_debouncedFetchProducts", m(() => {
55
+ n(this, "_debouncedFetchProducts", h(() => {
51
56
  this.store.fetchRecommendationProducts();
52
57
  }, 500));
53
58
  /**
@@ -61,16 +66,16 @@ class Q extends g {
61
66
  * count. The store pads products to the configured size, so in-place only
62
67
  * fails when the size actually changed.
63
68
  */
64
- s(this, "_debouncedRegenerateWithProducts", m(() => {
69
+ n(this, "_debouncedRegenerateWithProducts", h(() => {
65
70
  const t = this.store.recommendationProducts;
66
- if (!this.currentNode || !this.api || D(this.currentNode))
71
+ if (!this.currentNode || !this.api || w(this.currentNode))
67
72
  return;
68
73
  const e = this.api.getDocumentModifier();
69
- E({
74
+ A({
70
75
  currentNode: this.currentNode,
71
76
  documentModifier: e,
72
77
  products: t
73
- }) || A({
78
+ }) || v({
74
79
  currentNode: this.currentNode,
75
80
  documentModifier: e,
76
81
  products: t
@@ -78,23 +83,32 @@ class Q extends g {
78
83
  }, 100));
79
84
  }
80
85
  getId() {
81
- return w;
86
+ return F;
82
87
  }
83
- getTemplate() {
84
- return this.algorithmControl = new N(), this.localeControl = new b(), this.currencyControl = new R(), this.productCountControl = new O(), this.productLayoutControl = new P(), this.filtersControl = new I(), this.shuffleControl = new S(), this.pricePlacementControl = new T(), this.layoutOrientationControl = new _(), [
88
+ get _subControls() {
89
+ return [
90
+ this.layoutOrientationControl,
91
+ this.productCountControl,
85
92
  this.algorithmControl,
86
93
  this.localeControl,
87
94
  this.currencyControl,
88
- this.productCountControl,
89
95
  this.productLayoutControl,
90
96
  this.filtersControl,
91
97
  this.shuffleControl,
92
98
  this.pricePlacementControl,
93
- this.layoutOrientationControl
94
- ].forEach((e) => {
95
- e.api = this.api;
99
+ this.strategyControl
100
+ ];
101
+ }
102
+ getTemplate() {
103
+ var t;
104
+ return this.rrsEnabled = p().isFeatureEnabled("reusableRecommendationStrategy"), this._subControls.forEach((e) => {
105
+ var o;
106
+ return (o = e == null ? void 0 : e.onDestroy) == null ? void 0 : o.call(e);
107
+ }), this.algorithmControl = new I(), this.localeControl = new S(), this.currencyControl = new R(), this.productCountControl = new P(), this.productLayoutControl = new L(), this.filtersControl = new b(), this.shuffleControl = new k(), this.pricePlacementControl = new O(), this.layoutOrientationControl = new T(), this.strategyControl = this.rrsEnabled ? new E() : null, this._subControls.forEach((e) => {
108
+ e && (e.api = this.api);
96
109
  }), `
97
110
  <div class="recommendation-controls-container">
111
+ ${((t = this.strategyControl) == null ? void 0 : t.getTemplate()) ?? ""}
98
112
  ${this.layoutOrientationControl.getTemplate()}
99
113
  ${this.productCountControl.getTemplate()}
100
114
  ${this.productLayoutControl.getTemplate()}
@@ -107,50 +121,38 @@ class Q extends g {
107
121
  </div>
108
122
  `;
109
123
  }
124
+ _showControlsForBlock(t) {
125
+ var i;
126
+ const e = (i = this.getContainer()) == null ? void 0 : i.querySelector(".recommendation-controls-container");
127
+ if (!e)
128
+ return;
129
+ const o = this._getRecommendationIdFromNode(t) === null ? null : m.getConfig(t), r = this.rrsEnabled && !!o && (!!(o != null && o.strategyId) || ((o == null ? void 0 : o.configVersion) ?? 0) >= _);
130
+ e.classList.toggle("strategy-block", r);
131
+ }
110
132
  async onRender() {
111
133
  var o;
112
134
  const t = this._getRecommendationIdFromNode(this.currentNode), e = t ?? this.store.currentRecommendationId;
113
- if (e !== null && this.store.setCurrentBlock(e), t !== null && !this.syncedBlockIds.has(t) && (this.syncedBlockIds.add(t), this._syncNodeConfigToStore()), this._listenStateUpdates(), e !== null && ((o = this.store.blockStates[e]) != null && o.isInitialized)) {
135
+ if (e !== null && this.store.setCurrentBlock(e), t !== null && !this.syncedBlockIds.has(t) && (this.syncedBlockIds.add(t), this._syncNodeConfigToStore()), this._listenStateUpdates(), this._showControlsForBlock(this.currentNode), e !== null && ((o = this.store.blockStates[e]) != null && o.isInitialized)) {
114
136
  this._initializeSubControls();
115
137
  return;
116
138
  }
117
139
  await this._fetchBlockData(e), this._initializeSubControls();
118
140
  }
119
141
  onTemplateNodeUpdated(t) {
120
- var r;
142
+ var o;
121
143
  super.onTemplateNodeUpdated(t);
122
144
  const e = this._getRecommendationIdFromNode(t);
123
- e !== null && e !== this.store.currentRecommendationId && this.store.setCurrentBlock(e), e !== null && !this.syncedBlockIds.has(e) && (this.syncedBlockIds.add(e), this._syncNodeConfigToStore()), e !== null && !((r = this.store.blockStates[e]) != null && r.isInitialized) && this._fetchBlockData(e).then(() => {
145
+ e !== null && e !== this.store.currentRecommendationId && this.store.setCurrentBlock(e), e !== null && !this.syncedBlockIds.has(e) && (this.syncedBlockIds.add(e), this._syncNodeConfigToStore()), this._showControlsForBlock(t), e !== null && !((o = this.store.blockStates[e]) != null && o.isInitialized) && this._fetchBlockData(e).then(() => {
124
146
  this._initializeSubControls();
125
- }), [
126
- this.layoutOrientationControl,
127
- this.productCountControl,
128
- this.algorithmControl,
129
- this.localeControl,
130
- this.currencyControl,
131
- this.productLayoutControl,
132
- this.filtersControl,
133
- this.shuffleControl,
134
- this.pricePlacementControl
135
- ].forEach((n) => {
147
+ }), this._subControls.forEach((r) => {
136
148
  var i;
137
- n != null && n.api && (n.currentNode = t, (i = n.onTemplateNodeUpdated) == null || i.call(n, t));
149
+ r != null && r.api && (r.currentNode = t, (i = r.onTemplateNodeUpdated) == null || i.call(r, t));
138
150
  });
139
151
  }
140
152
  onDestroy() {
141
- this.storeUnsubscription(), [
142
- this.layoutOrientationControl,
143
- this.productCountControl,
144
- this.algorithmControl,
145
- this.localeControl,
146
- this.currencyControl,
147
- this.productLayoutControl,
148
- this.filtersControl,
149
- this.shuffleControl,
150
- this.pricePlacementControl
151
- ].forEach((e) => {
152
- var o;
153
- return (o = e == null ? void 0 : e.onDestroy) == null ? void 0 : o.call(e);
153
+ this.storeUnsubscription(), this._subControls.forEach((t) => {
154
+ var e;
155
+ return (e = t == null ? void 0 : t.onDestroy) == null ? void 0 : e.call(t);
154
156
  });
155
157
  }
156
158
  /**
@@ -158,25 +160,14 @@ class Q extends g {
158
160
  * Each sub-control manages its own form values and event listeners
159
161
  */
160
162
  _initializeSubControls() {
161
- [
162
- this.layoutOrientationControl,
163
- this.productCountControl,
164
- this.algorithmControl,
165
- this.localeControl,
166
- this.currencyControl,
167
- this.productLayoutControl,
168
- this.filtersControl,
169
- this.shuffleControl,
170
- this.pricePlacementControl
171
- ].forEach((e) => {
172
- var o;
173
- e && (e.api = this.api, e.currentNode = this.currentNode, (o = e.onRender) == null || o.call(e));
163
+ this._subControls.forEach((t) => {
164
+ var e;
165
+ t && (t.api = this.api, t.currentNode = this.currentNode, (e = t.onRender) == null || e.call(t));
174
166
  });
175
167
  }
176
168
  /**
177
169
  * Syncs persisted node config into the Pinia store's block state.
178
170
  *
179
- * setCurrentBlock() creates a default entry (USD, en_US, mostPopular).
180
171
  * For saved templates, the real config lives in the node (e.g., TRY, tr_TR).
181
172
  * This method reads it and patches the store so fetchRecommendationProducts()
182
173
  * uses the correct values.
@@ -186,9 +177,10 @@ class Q extends g {
186
177
  */
187
178
  _syncNodeConfigToStore() {
188
179
  var r;
189
- const t = h.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
180
+ const t = m.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
190
181
  this.store.patchCurrentBlockConfig({
191
182
  strategy: t.strategy,
183
+ strategyId: t.strategyId,
192
184
  language: t.language,
193
185
  size: t.size,
194
186
  productIds: t.productIds,
@@ -249,36 +241,36 @@ class Q extends g {
249
241
  _applySmartDefaults() {
250
242
  if (!this.currentNode || !this.api)
251
243
  return;
252
- const t = h.getConfig(this.currentNode), e = {};
253
- let o = null, r = null, n = null;
254
- if (t.currency.code === c.currency.code) {
255
- const { currencyList: i } = this.store;
256
- i.length > 0 && (i.some(
257
- (u) => u.value === `price.${c.currency.code}`
258
- ) || (o = i[0].value.replace("price.", ""), e.currency = {
259
- ...c.currency,
244
+ const t = m.getConfig(this.currentNode), e = {};
245
+ let o = null, r = null, i = null;
246
+ if (t.currency.code === a.currency.code) {
247
+ const { currencyList: s } = this.store;
248
+ s.length > 0 && (s.some(
249
+ (u) => u.value === `price.${a.currency.code}`
250
+ ) || (o = s[0].value.replace("price.", ""), e.currency = {
251
+ ...a.currency,
260
252
  code: o,
261
253
  symbol: o
262
254
  }));
263
255
  }
264
- if (t.strategy === c.strategy) {
265
- const i = this.store.getActivePredictiveAlgorithms;
266
- i.length > 0 && (i.some(
267
- (u) => u.value === c.strategy
268
- ) || (r = i[0].value, e.strategy = r));
256
+ if (t.strategy === a.strategy) {
257
+ const s = this.store.getActivePredictiveAlgorithms;
258
+ s.length > 0 && (s.some(
259
+ (u) => u.value === a.strategy
260
+ ) || (r = s[0].value, e.strategy = r));
269
261
  }
270
- if (t.language === c.language) {
271
- const i = this.store.getLanguages;
272
- i.length > 0 && (i.some(
273
- (u) => u.value === c.language
274
- ) || (n = i[0].value, e.language = n));
262
+ if (t.language === a.language) {
263
+ const s = this.store.getLanguages;
264
+ s.length > 0 && (s.some(
265
+ (u) => u.value === a.language
266
+ ) || (i = s[0].value, e.language = i));
275
267
  }
276
- !o && !r && !n || (h.updateConfig(
268
+ !o && !r && !i || (m.updateConfig(
277
269
  this.api,
278
270
  this.currentNode,
279
271
  e,
280
272
  "Applied smart defaults"
281
- ), o && e.currency && L({
273
+ ), o && e.currency && D({
282
274
  currentNode: this.currentNode,
283
275
  documentModifier: this.api.getDocumentModifier(),
284
276
  currency: e.currency
@@ -288,24 +280,24 @@ class Q extends g {
288
280
  name: o,
289
281
  value: o,
290
282
  symbol: o,
291
- alignment: c.currency.alignment === "before" ? "0" : "1",
292
- decimalCount: c.currency.decimalCount.toString(),
293
- decimalSeparator: c.currency.decimalSeparator,
294
- thousandSeparator: c.currency.thousandSeparator
283
+ alignment: a.currency.alignment === "before" ? "0" : "1",
284
+ decimalCount: a.currency.decimalCount.toString(),
285
+ decimalSeparator: a.currency.decimalSeparator,
286
+ thousandSeparator: a.currency.thousandSeparator
295
287
  }
296
288
  } : {},
297
289
  ...r ? { strategy: r } : {},
298
- ...n ? { language: n } : {}
290
+ ...i ? { language: i } : {}
299
291
  }, { triggerRefetch: !1 }));
300
292
  }
301
293
  /**
302
294
  * Reads the recommendation-id attribute from the block element within the node
303
295
  */
304
296
  _getRecommendationIdFromNode(t) {
305
- const e = k(t);
297
+ const e = B(t);
306
298
  if (!e || !("getAttribute" in e))
307
299
  return null;
308
- const o = e.getAttribute(v);
300
+ const o = e.getAttribute(x);
309
301
  if (!o)
310
302
  return null;
311
303
  const r = parseInt(o);
@@ -328,64 +320,68 @@ class Q extends g {
328
320
  const { store: t } = this;
329
321
  let e = t.recommendationProducts, o = t.$state.configVersion, r = t.currentRecommendationId;
330
322
  this.storeUnsubscription = t.$subscribe(() => {
331
- const n = t.currentRecommendationId;
332
- if (n !== r) {
333
- r = n, e = t.recommendationProducts, o = t.$state.configVersion;
323
+ const i = t.currentRecommendationId;
324
+ if (i !== r) {
325
+ r = i, e = t.recommendationProducts, o = t.$state.configVersion;
334
326
  return;
335
327
  }
336
- const i = t.$state.configVersion;
337
- i !== o && (o = i, this._persistFiltersToNodeConfig(), this._debouncedFetchProducts());
338
- const a = t.recommendationProducts, u = a !== e, C = Array.isArray(a) && a.length > 0;
339
- u && C && (e = a, this._debouncedRegenerateWithProducts());
328
+ const s = t.$state.configVersion;
329
+ s !== o && (o = s, this._persistFiltersToNodeConfig(), this._debouncedFetchProducts());
330
+ const l = t.recommendationProducts, u = l !== e, f = Array.isArray(l) && l.length > 0;
331
+ u && f && (e = l, this._debouncedRegenerateWithProducts());
340
332
  });
341
333
  }
342
334
  /**
343
- * Persists the current filter state from Pinia store to the Stripo node config.
344
- * This ensures filters survive template save/reload cycles.
335
+ * Persists filter + strategy state to the Stripo node config so it survives
336
+ * save/reload (strategyId must reach esd-ext-config before any save).
337
+ * `size` rides along: assigning a strategy writes it to the store only, and a
338
+ * stale node config would rebuild the block against the old slot count.
345
339
  */
346
340
  _persistFiltersToNodeConfig() {
347
341
  if (!this.currentNode || !this.api)
348
342
  return;
349
- const { filters: t } = this.store.recommendationConfigs, e = h.getConfig(this.currentNode).filters;
350
- JSON.stringify(e) !== JSON.stringify(t) && h.updateConfig(
343
+ const { filters: t, strategyId: e, size: o } = this.store.recommendationConfigs, r = m.getConfig(this.currentNode);
344
+ JSON.stringify(r.filters) === JSON.stringify(t) && r.strategyId === e && r.size === o || m.updateConfig(
351
345
  this.api,
352
346
  this.currentNode,
353
- { filters: t },
347
+ { filters: t, strategyId: e, size: o },
354
348
  "Update recommendation filters"
355
349
  );
356
350
  }
357
351
  }
358
352
  export {
359
- tt as ALGORITHM_CONTROL_ID,
360
- N as AlgorithmControl,
361
- w as CONTROL_BLOCK_ID,
362
- ot as CURRENCY_CONTROL_ID,
353
+ it as ALGORITHM_CONTROL_ID,
354
+ I as AlgorithmControl,
355
+ F as CONTROL_BLOCK_ID,
356
+ at as CURRENCY_CONTROL_ID,
363
357
  R as CurrencyControl,
364
- nt as FILTERS_CONTROL_ID,
365
- I as FiltersControl,
366
- st as LAYOUT_ORIENTATION_CONTROL_ID,
367
- lt as LOCALE_CONTROL_ID,
368
- _ as LayoutOrientationControl,
369
- b as LocaleControl,
370
- ut as PRICE_PLACEMENT_CONTROL_ID,
371
- ht as PRODUCT_COUNT_CONTROL_ID,
372
- Ct as PRODUCT_LAYOUT_CONTROL_ID,
373
- T as PricePlacementControl,
374
- O as ProductCountControl,
375
- P as ProductLayoutControl,
376
- Q as RecommendationBlockControl,
377
- pt as SHUFFLE_CONTROL_ID,
378
- S as ShuffleControl,
379
- yt as adjustProductsToSize,
380
- Nt as formatProductPrice,
381
- k as getBlockElement,
382
- Rt as getCardComposition,
383
- It as getCurrentLayout,
384
- D as isPartnerManagedBlock,
385
- _t as regenerateMobileProductRows,
386
- A as regenerateProductRowsWithStyles,
387
- L as setCurrencyAttributes,
388
- bt as updatePricesInPlace,
389
- E as updateProductContentInPlace,
390
- Tt as updateSingleProductContent
358
+ lt as FILTERS_CONTROL_ID,
359
+ b as FiltersControl,
360
+ dt as LAYOUT_ORIENTATION_CONTROL_ID,
361
+ ht as LOCALE_CONTROL_ID,
362
+ T as LayoutOrientationControl,
363
+ S as LocaleControl,
364
+ Ct as PRICE_PLACEMENT_CONTROL_ID,
365
+ pt as PRODUCT_COUNT_CONTROL_ID,
366
+ _t as PRODUCT_LAYOUT_CONTROL_ID,
367
+ O as PricePlacementControl,
368
+ P as ProductCountControl,
369
+ L as ProductLayoutControl,
370
+ ot as RecommendationBlockControl,
371
+ It as SHUFFLE_CONTROL_ID,
372
+ bt as STRATEGY_CONTROL_ID,
373
+ k as ShuffleControl,
374
+ E as StrategyControl,
375
+ St as adjustProductsToSize,
376
+ Ot as formatProductPrice,
377
+ B as getBlockElement,
378
+ Pt as getCardComposition,
379
+ Lt as getCurrentLayout,
380
+ w as isPartnerManagedBlock,
381
+ kt as regenerateMobileProductRows,
382
+ v as regenerateProductRowsWithStyles,
383
+ D as setCurrencyAttributes,
384
+ Et as updatePricesInPlace,
385
+ A as updateProductContentInPlace,
386
+ Dt as updateSingleProductContent
391
387
  };
@@ -0,0 +1,124 @@
1
+ var d = Object.defineProperty;
2
+ var y = (r, s, t) => s in r ? d(r, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[s] = t;
3
+ var o = (r, s, t) => y(r, typeof s != "symbol" ? s + "" : s, t);
4
+ import { ACADEMY_LINKS as m } from "../../../../../enums/academy.js";
5
+ import { CommonControl as h } from "../../../common-control.js";
6
+ import { useRecommendationExtensionStore as u } from "../../store/recommendation.js";
7
+ const p = "recommendation-strategy-control";
8
+ class f extends h {
9
+ constructor() {
10
+ super(...arguments);
11
+ o(this, "store", u());
12
+ o(this, "storeUnsubscription", () => {
13
+ });
14
+ o(this, "listeners", []);
15
+ o(this, "lastPaintedState", null);
16
+ }
17
+ getId() {
18
+ return p;
19
+ }
20
+ getTemplate() {
21
+ const t = this.api.translate(
22
+ "You can assign a recommendation strategy by selecting an existing one or creating a new one to show specific content."
23
+ ), e = this.api.translate("For more information, you can"), a = this.api.translate("visit Academy");
24
+ return `
25
+ <div class="strategy-control-container">
26
+ <div class="strategy-control-header">
27
+ <h3 class="strategy-control-title">${this.api.translate("Recommendation Strategy")}</h3>
28
+ </div>
29
+ <div class="strategy-control-description-row">
30
+ <p class="strategy-control-description">
31
+ ${t}
32
+ ${e}
33
+ <a
34
+ href="${m.EMAIL_RECOMMENDATION_BLOCK}"
35
+ target="_blank"
36
+ rel="noopener noreferrer">${a}</a>.
37
+ </p>
38
+ </div>
39
+ <div data-strategy-empty-state>
40
+ ${this._GuTwoColumns([
41
+ this._GuButton({
42
+ name: "assignStrategy",
43
+ label: this.api.translate("Assign Strategy"),
44
+ id: "guido__btn-assign-strategy",
45
+ className: "strategy-control-cta on"
46
+ }),
47
+ this._GuButton({
48
+ name: "createStrategy",
49
+ label: this.api.translate("Create New Strategy"),
50
+ id: "guido__btn-create-strategy",
51
+ className: "strategy-control-cta primary",
52
+ disabled: !0
53
+ })
54
+ ], "strategy-control-cta-row")}
55
+ </div>
56
+ <div data-strategy-assigned-state style="display: none;">
57
+ <div class="strategy-control-name-band">
58
+ <span class="strategy-control-name" data-strategy-name></span>
59
+ </div>
60
+ <div class="strategy-control-actions">
61
+ ${this._strategyAction({
62
+ id: "guido__btn-change-strategy",
63
+ label: this.api.translate("Change"),
64
+ modifier: "change"
65
+ })}
66
+ ${this._strategyAction({
67
+ id: "guido__btn-remove-strategy",
68
+ label: this.api.translate("Remove"),
69
+ modifier: "remove"
70
+ })}
71
+ </div>
72
+ </div>
73
+ </div>
74
+ `;
75
+ }
76
+ _strategyAction({ id: t, label: e, modifier: a }) {
77
+ return `
78
+ <button
79
+ id="${t}"
80
+ type="button"
81
+ class="strategy-control-action strategy-control-action--${a}">
82
+ <span>${e}</span>
83
+ </button>
84
+ `;
85
+ }
86
+ onRender() {
87
+ this._teardown(), this._setupButtonListeners(), this._renderState(), this.storeUnsubscription = this.store.$subscribe(() => {
88
+ this._renderState();
89
+ }), this.store.recommendationConfigs.strategyId && !this.store.strategies.length && this.store.fetchStrategies().catch(() => {
90
+ });
91
+ }
92
+ onDestroy() {
93
+ this._teardown();
94
+ }
95
+ _teardown() {
96
+ this.storeUnsubscription(), this.storeUnsubscription = () => {
97
+ }, this.lastPaintedState = null, this.listeners.forEach(({ element: t, handler: e }) => t.removeEventListener("click", e)), this.listeners = [];
98
+ }
99
+ _setupButtonListeners() {
100
+ const t = this.getContainer();
101
+ if (!t)
102
+ return;
103
+ const e = (a, n) => {
104
+ const i = t.querySelector(a);
105
+ i && (i.addEventListener("click", n), this.listeners.push({ element: i, handler: n }));
106
+ };
107
+ e("#guido__btn-assign-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-remove-strategy", () => this.store.removeStrategy());
108
+ }
109
+ _renderState() {
110
+ var l;
111
+ const { strategyId: t } = this.store.recommendationConfigs, e = t ? ((l = this.store.assignedStrategy) == null ? void 0 : l.name) ?? "" : "", a = `${t}\0${e}`;
112
+ if (a === this.lastPaintedState)
113
+ return;
114
+ const n = this.getContainer();
115
+ if (!n)
116
+ return;
117
+ const i = n.querySelector("[data-strategy-empty-state]"), c = n.querySelector("[data-strategy-assigned-state]"), g = n.querySelector("[data-strategy-name]");
118
+ !i || !c || (i.style.display = t ? "none" : "", c.style.display = t ? "" : "none", g && t && (g.textContent = e || `#${t}`), this.lastPaintedState = a);
119
+ }
120
+ }
121
+ export {
122
+ p as STRATEGY_CONTROL_ID,
123
+ f as StrategyControl
124
+ };