@useinsider/guido 3.17.0-beta.dc7f4d2 → 3.17.0-beta.e6704da
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 +5 -5
- package/dist/components/Guido.vue2.js +77 -77
- package/dist/components/organisms/AutoSaveController.vue2.js +8 -9
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +18 -0
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +70 -0
- package/dist/components/organisms/extensions/recommendation/StrategyInfoBox.vue.js +20 -0
- package/dist/components/organisms/extensions/recommendation/StrategyInfoBox.vue2.js +55 -0
- package/dist/components/organisms/header/EditorActions.vue.js +2 -2
- package/dist/components/organisms/header/EditorActions.vue2.js +43 -74
- package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
- package/dist/components/organisms/header/LeftSlot.vue2.js +23 -46
- package/dist/components/wrappers/WpDrawer.vue.js +7 -9
- package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
- package/dist/composables/useCustomInterfaceAppearance.js +19 -16
- package/dist/composables/useHtmlCompiler.js +26 -37
- package/dist/composables/useHtmlValidator.js +0 -2
- package/dist/composables/useRecommendation.js +41 -34
- package/dist/composables/useSave.js +41 -84
- package/dist/composables/validators/useCouponBlockValidator.js +21 -24
- package/dist/composables/validators/useUnsubscribeBlockValidator.js +27 -34
- package/dist/config/migrator/recommendationMigrator.js +6 -4
- package/dist/enums/academy.js +2 -1
- package/dist/enums/date.js +4 -3
- package/dist/enums/extensions/recommendationBlock.js +25 -23
- package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +13 -11
- package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +96 -95
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +156 -154
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +141 -0
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +223 -82
- package/dist/extensions/Blocks/common-control.js +22 -19
- package/dist/guido.css +1 -1
- package/dist/services/recommendationApi.js +78 -29
- package/dist/src/@types/config/schemas.d.ts +12 -0
- package/dist/src/components/Guido.vue.d.ts +1 -17
- package/dist/src/components/organisms/{validation/ValidationErrorDrawer.vue.d.ts → extensions/recommendation/AssignStrategyDrawer.vue.d.ts} +1 -0
- package/dist/src/components/organisms/extensions/recommendation/StrategyInfoBox.vue.d.ts +24 -0
- package/dist/src/components/organisms/header/EditorActions.vue.d.ts +1 -17
- package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -17
- package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -17
- package/dist/src/components/wrappers/WpDrawer.vue.d.ts +3 -4
- package/dist/src/composables/useConfig.d.ts +2 -0
- package/dist/src/composables/useHtmlValidator.d.ts +0 -21
- package/dist/src/composables/useRecommendation.d.ts +1 -0
- package/dist/src/composables/useSave.d.ts +1 -6
- package/dist/src/composables/validators/useCouponBlockValidator.d.ts +0 -3
- package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +0 -10
- 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/controls/main/index.d.ts +14 -3
- package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +29 -0
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +214 -15
- 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 +43 -0
- package/dist/src/services/recommendationApi.d.ts +4 -1
- package/dist/src/stores/config.d.ts +18 -5
- package/dist/src/utils/templatePreparation.d.ts +0 -30
- package/dist/static/styles/components/recommendation-strategy.css.js +171 -0
- package/dist/stores/config.js +6 -13
- package/dist/utils/dateUtil.js +23 -10
- package/dist/utils/templatePreparation.js +50 -50
- package/package.json +2 -1
- package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +0 -20
- package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +0 -48
- package/dist/composables/useSaveValidation.js +0 -279
- package/dist/composables/useSaveValidationRollout.js +0 -9
- package/dist/enums/save-validation.js +0 -4
- package/dist/src/@types/save-validation.d.ts +0 -19
- package/dist/src/composables/useSaveValidation.d.ts +0 -6
- package/dist/src/composables/useSaveValidationRollout.d.ts +0 -3
- package/dist/src/enums/save-validation.d.ts +0 -27
- package/dist/src/stores/save-validation.d.ts +0 -22
- package/dist/stores/save-validation.js +0 -30
|
@@ -1,53 +1,57 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
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 { 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 _ } from "./algorithm.js";
|
|
10
|
+
import { ALGORITHM_CONTROL_ID as nt } from "./algorithm.js";
|
|
11
|
+
import { CurrencyControl as I } from "./currency.js";
|
|
12
|
+
import { CURRENCY_CONTROL_ID as st } from "./currency.js";
|
|
13
|
+
import { FiltersControl as R } from "./filters.js";
|
|
14
|
+
import { FILTERS_CONTROL_ID as ct } from "./filters.js";
|
|
15
|
+
import { LayoutOrientationControl as T } from "./layoutOrientation.js";
|
|
16
|
+
import { LAYOUT_ORIENTATION_CONTROL_ID as ut } from "./layoutOrientation.js";
|
|
16
17
|
import { LocaleControl as b } from "./locale.js";
|
|
17
|
-
import { LOCALE_CONTROL_ID as
|
|
18
|
-
import { PricePlacementControl as
|
|
19
|
-
import { PRICE_PLACEMENT_CONTROL_ID as
|
|
20
|
-
import { ProductCountControl as
|
|
21
|
-
import { PRODUCT_COUNT_CONTROL_ID as
|
|
18
|
+
import { LOCALE_CONTROL_ID as mt } from "./locale.js";
|
|
19
|
+
import { PricePlacementControl as O } from "./pricePlacement.js";
|
|
20
|
+
import { PRICE_PLACEMENT_CONTROL_ID as ft } from "./pricePlacement.js";
|
|
21
|
+
import { ProductCountControl as S } from "./productCount.js";
|
|
22
|
+
import { PRODUCT_COUNT_CONTROL_ID as gt } from "./productCount.js";
|
|
22
23
|
import { ProductLayoutControl as P } from "./productLayout.js";
|
|
23
|
-
import { PRODUCT_LAYOUT_CONTROL_ID as
|
|
24
|
-
import { ShuffleControl as
|
|
25
|
-
import { SHUFFLE_CONTROL_ID as
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
import { PRODUCT_LAYOUT_CONTROL_ID as yt } from "./productLayout.js";
|
|
25
|
+
import { ShuffleControl as L } from "./shuffle.js";
|
|
26
|
+
import { SHUFFLE_CONTROL_ID as _t } from "./shuffle.js";
|
|
27
|
+
import { StrategyControl as k } from "./strategy.js";
|
|
28
|
+
import { STRATEGY_CONTROL_ID as Rt } from "./strategy.js";
|
|
29
|
+
import { setCurrencyAttributes as D, getBlockElement as E, isPartnerManagedBlock as v, updateProductContentInPlace as A, regenerateProductRowsWithStyles as w } from "./utils.js";
|
|
30
|
+
import { adjustProductsToSize as bt, formatProductPrice as Ot, getCardComposition as St, getCurrentLayout as Pt, regenerateMobileProductRows as Lt, updatePricesInPlace as kt, updateSingleProductContent as Dt } from "./utils.js";
|
|
31
|
+
import { useDebounceFn as h } from "../../../../../node_modules/@vueuse/shared/index.js";
|
|
32
|
+
const x = "recommendation-id", B = "ui-elements-recommendation-block";
|
|
33
|
+
class et extends y {
|
|
31
34
|
constructor() {
|
|
32
35
|
super(...arguments);
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
n(this, "store", N());
|
|
37
|
+
n(this, "storeUnsubscription", () => {
|
|
35
38
|
});
|
|
36
|
-
|
|
39
|
+
n(this, "syncedBlockIds", /* @__PURE__ */ new Set());
|
|
37
40
|
// Sub-control instances for lifecycle management
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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);
|
|
47
51
|
/**
|
|
48
52
|
* Debounced product fetch to prevent rapid API calls during config changes
|
|
49
53
|
*/
|
|
50
|
-
|
|
54
|
+
n(this, "_debouncedFetchProducts", h(() => {
|
|
51
55
|
this.store.fetchRecommendationProducts();
|
|
52
56
|
}, 500));
|
|
53
57
|
/**
|
|
@@ -61,16 +65,16 @@ class Q extends g {
|
|
|
61
65
|
* count. The store pads products to the configured size, so in-place only
|
|
62
66
|
* fails when the size actually changed.
|
|
63
67
|
*/
|
|
64
|
-
|
|
68
|
+
n(this, "_debouncedRegenerateWithProducts", h(() => {
|
|
65
69
|
const t = this.store.recommendationProducts;
|
|
66
|
-
if (!this.currentNode || !this.api ||
|
|
70
|
+
if (!this.currentNode || !this.api || v(this.currentNode))
|
|
67
71
|
return;
|
|
68
72
|
const e = this.api.getDocumentModifier();
|
|
69
|
-
|
|
73
|
+
A({
|
|
70
74
|
currentNode: this.currentNode,
|
|
71
75
|
documentModifier: e,
|
|
72
76
|
products: t
|
|
73
|
-
}) ||
|
|
77
|
+
}) || w({
|
|
74
78
|
currentNode: this.currentNode,
|
|
75
79
|
documentModifier: e,
|
|
76
80
|
products: t
|
|
@@ -78,22 +82,40 @@ class Q extends g {
|
|
|
78
82
|
}, 100));
|
|
79
83
|
}
|
|
80
84
|
getId() {
|
|
81
|
-
return
|
|
85
|
+
return B;
|
|
82
86
|
}
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
/** Every sub-control the coordinator owns, in panel order. */
|
|
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.
|
|
94
|
-
]
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
this.strategyControl
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
getTemplate() {
|
|
103
|
+
const t = p().isFeatureEnabled("reusableRecommendationStrategy");
|
|
104
|
+
return 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 = t ? null : new _(), this.localeControl = new b(), this.currencyControl = new I(), this.productCountControl = t ? null : new S(), this.productLayoutControl = new P(), this.filtersControl = t ? null : new R(), this.shuffleControl = t ? null : new L(), this.pricePlacementControl = new O(), this.layoutOrientationControl = new T(), this.strategyControl = t ? new k() : null, this._subControls.forEach((e) => {
|
|
108
|
+
e && (e.api = this.api);
|
|
109
|
+
}), t ? `
|
|
110
|
+
<div class="recommendation-controls-container">
|
|
111
|
+
${this.strategyControl.getTemplate()}
|
|
112
|
+
${this.layoutOrientationControl.getTemplate()}
|
|
113
|
+
${this.localeControl.getTemplate()}
|
|
114
|
+
${this.currencyControl.getTemplate()}
|
|
115
|
+
${this.pricePlacementControl.getTemplate()}
|
|
116
|
+
${this.productLayoutControl.getTemplate()}
|
|
117
|
+
</div>
|
|
118
|
+
` : `
|
|
97
119
|
<div class="recommendation-controls-container">
|
|
98
120
|
${this.layoutOrientationControl.getTemplate()}
|
|
99
121
|
${this.productCountControl.getTemplate()}
|
|
@@ -117,40 +139,20 @@ class Q extends g {
|
|
|
117
139
|
await this._fetchBlockData(e), this._initializeSubControls();
|
|
118
140
|
}
|
|
119
141
|
onTemplateNodeUpdated(t) {
|
|
120
|
-
var
|
|
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 && !((
|
|
145
|
+
e !== null && e !== this.store.currentRecommendationId && this.store.setCurrentBlock(e), e !== null && !this.syncedBlockIds.has(e) && (this.syncedBlockIds.add(e), this._syncNodeConfigToStore()), e !== null && !((o = this.store.blockStates[e]) != null && o.isInitialized) && this._fetchBlockData(e).then(() => {
|
|
124
146
|
this._initializeSubControls();
|
|
125
|
-
}),
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
this.algorithmControl,
|
|
129
|
-
this.localeControl,
|
|
130
|
-
this.currencyControl,
|
|
131
|
-
this.productLayoutControl,
|
|
132
|
-
this.filtersControl,
|
|
133
|
-
this.shuffleControl,
|
|
134
|
-
this.pricePlacementControl
|
|
135
|
-
].forEach((n) => {
|
|
136
|
-
var i;
|
|
137
|
-
n != null && n.api && (n.currentNode = t, (i = n.onTemplateNodeUpdated) == null || i.call(n, t));
|
|
147
|
+
}), this._subControls.forEach((r) => {
|
|
148
|
+
var s;
|
|
149
|
+
r != null && r.api && (r.currentNode = t, (s = r.onTemplateNodeUpdated) == null || s.call(r, t));
|
|
138
150
|
});
|
|
139
151
|
}
|
|
140
152
|
onDestroy() {
|
|
141
|
-
this.storeUnsubscription(),
|
|
142
|
-
|
|
143
|
-
|
|
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,19 +160,9 @@ class Q extends g {
|
|
|
158
160
|
* Each sub-control manages its own form values and event listeners
|
|
159
161
|
*/
|
|
160
162
|
_initializeSubControls() {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
this.
|
|
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
|
/**
|
|
@@ -186,9 +178,10 @@ class Q extends g {
|
|
|
186
178
|
*/
|
|
187
179
|
_syncNodeConfigToStore() {
|
|
188
180
|
var r;
|
|
189
|
-
const t =
|
|
181
|
+
const t = m.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
|
|
190
182
|
this.store.patchCurrentBlockConfig({
|
|
191
183
|
strategy: t.strategy,
|
|
184
|
+
strategyId: t.strategyId,
|
|
192
185
|
language: t.language,
|
|
193
186
|
size: t.size,
|
|
194
187
|
productIds: t.productIds,
|
|
@@ -249,36 +242,36 @@ class Q extends g {
|
|
|
249
242
|
_applySmartDefaults() {
|
|
250
243
|
if (!this.currentNode || !this.api)
|
|
251
244
|
return;
|
|
252
|
-
const t =
|
|
253
|
-
let o = null, r = null,
|
|
254
|
-
if (t.currency.code ===
|
|
245
|
+
const t = m.getConfig(this.currentNode), e = {};
|
|
246
|
+
let o = null, r = null, s = null;
|
|
247
|
+
if (t.currency.code === a.currency.code) {
|
|
255
248
|
const { currencyList: i } = this.store;
|
|
256
249
|
i.length > 0 && (i.some(
|
|
257
|
-
(u) => u.value === `price.${
|
|
250
|
+
(u) => u.value === `price.${a.currency.code}`
|
|
258
251
|
) || (o = i[0].value.replace("price.", ""), e.currency = {
|
|
259
|
-
...
|
|
252
|
+
...a.currency,
|
|
260
253
|
code: o,
|
|
261
254
|
symbol: o
|
|
262
255
|
}));
|
|
263
256
|
}
|
|
264
|
-
if (t.strategy ===
|
|
257
|
+
if (t.strategy === a.strategy) {
|
|
265
258
|
const i = this.store.getActivePredictiveAlgorithms;
|
|
266
259
|
i.length > 0 && (i.some(
|
|
267
|
-
(u) => u.value ===
|
|
260
|
+
(u) => u.value === a.strategy
|
|
268
261
|
) || (r = i[0].value, e.strategy = r));
|
|
269
262
|
}
|
|
270
|
-
if (t.language ===
|
|
263
|
+
if (t.language === a.language) {
|
|
271
264
|
const i = this.store.getLanguages;
|
|
272
265
|
i.length > 0 && (i.some(
|
|
273
|
-
(u) => u.value ===
|
|
274
|
-
) || (
|
|
266
|
+
(u) => u.value === a.language
|
|
267
|
+
) || (s = i[0].value, e.language = s));
|
|
275
268
|
}
|
|
276
|
-
!o && !r && !
|
|
269
|
+
!o && !r && !s || (m.updateConfig(
|
|
277
270
|
this.api,
|
|
278
271
|
this.currentNode,
|
|
279
272
|
e,
|
|
280
273
|
"Applied smart defaults"
|
|
281
|
-
), o && e.currency &&
|
|
274
|
+
), o && e.currency && D({
|
|
282
275
|
currentNode: this.currentNode,
|
|
283
276
|
documentModifier: this.api.getDocumentModifier(),
|
|
284
277
|
currency: e.currency
|
|
@@ -288,24 +281,24 @@ class Q extends g {
|
|
|
288
281
|
name: o,
|
|
289
282
|
value: o,
|
|
290
283
|
symbol: o,
|
|
291
|
-
alignment:
|
|
292
|
-
decimalCount:
|
|
293
|
-
decimalSeparator:
|
|
294
|
-
thousandSeparator:
|
|
284
|
+
alignment: a.currency.alignment === "before" ? "0" : "1",
|
|
285
|
+
decimalCount: a.currency.decimalCount.toString(),
|
|
286
|
+
decimalSeparator: a.currency.decimalSeparator,
|
|
287
|
+
thousandSeparator: a.currency.thousandSeparator
|
|
295
288
|
}
|
|
296
289
|
} : {},
|
|
297
290
|
...r ? { strategy: r } : {},
|
|
298
|
-
...
|
|
291
|
+
...s ? { language: s } : {}
|
|
299
292
|
}, { triggerRefetch: !1 }));
|
|
300
293
|
}
|
|
301
294
|
/**
|
|
302
295
|
* Reads the recommendation-id attribute from the block element within the node
|
|
303
296
|
*/
|
|
304
297
|
_getRecommendationIdFromNode(t) {
|
|
305
|
-
const e =
|
|
298
|
+
const e = E(t);
|
|
306
299
|
if (!e || !("getAttribute" in e))
|
|
307
300
|
return null;
|
|
308
|
-
const o = e.getAttribute(
|
|
301
|
+
const o = e.getAttribute(x);
|
|
309
302
|
if (!o)
|
|
310
303
|
return null;
|
|
311
304
|
const r = parseInt(o);
|
|
@@ -328,64 +321,73 @@ class Q extends g {
|
|
|
328
321
|
const { store: t } = this;
|
|
329
322
|
let e = t.recommendationProducts, o = t.$state.configVersion, r = t.currentRecommendationId;
|
|
330
323
|
this.storeUnsubscription = t.$subscribe(() => {
|
|
331
|
-
const
|
|
332
|
-
if (
|
|
333
|
-
r =
|
|
324
|
+
const s = t.currentRecommendationId;
|
|
325
|
+
if (s !== r) {
|
|
326
|
+
r = s, e = t.recommendationProducts, o = t.$state.configVersion;
|
|
334
327
|
return;
|
|
335
328
|
}
|
|
336
329
|
const i = t.$state.configVersion;
|
|
337
330
|
i !== o && (o = i, this._persistFiltersToNodeConfig(), this._debouncedFetchProducts());
|
|
338
|
-
const
|
|
339
|
-
u &&
|
|
331
|
+
const l = t.recommendationProducts, u = l !== e, f = Array.isArray(l) && l.length > 0;
|
|
332
|
+
u && f && (e = l, this._debouncedRegenerateWithProducts());
|
|
340
333
|
});
|
|
341
334
|
}
|
|
342
335
|
/**
|
|
343
|
-
* Persists the current filter state from Pinia store to the
|
|
344
|
-
* This ensures
|
|
336
|
+
* Persists the current filter + strategy state from Pinia store to the
|
|
337
|
+
* Stripo node config. This ensures they survive template save/reload cycles
|
|
338
|
+
* (strategyId must be in esd-ext-config before any save — SD-149105).
|
|
339
|
+
*
|
|
340
|
+
* `size` rides along because assigning a strategy overwrites it in the
|
|
341
|
+
* store only. Without this write, `_syncNodeConfigToStore` re-seeds the
|
|
342
|
+
* store from the stale node config on the next panel open, and a block
|
|
343
|
+
* whose saved HTML has the strategy's slot count gets rebuilt against the
|
|
344
|
+
* old one — resetting migrator-applied per-element styles.
|
|
345
345
|
*/
|
|
346
346
|
_persistFiltersToNodeConfig() {
|
|
347
347
|
if (!this.currentNode || !this.api)
|
|
348
348
|
return;
|
|
349
|
-
const { filters: t } = this.store.recommendationConfigs,
|
|
350
|
-
JSON.stringify(
|
|
349
|
+
const { filters: t, strategyId: e, size: o } = this.store.recommendationConfigs, r = m.getConfig(this.currentNode);
|
|
350
|
+
JSON.stringify(r.filters) === JSON.stringify(t) && r.strategyId === e && r.size === o || m.updateConfig(
|
|
351
351
|
this.api,
|
|
352
352
|
this.currentNode,
|
|
353
|
-
{ filters: t },
|
|
353
|
+
{ filters: t, strategyId: e, size: o },
|
|
354
354
|
"Update recommendation filters"
|
|
355
355
|
);
|
|
356
356
|
}
|
|
357
357
|
}
|
|
358
358
|
export {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
359
|
+
nt as ALGORITHM_CONTROL_ID,
|
|
360
|
+
_ as AlgorithmControl,
|
|
361
|
+
B as CONTROL_BLOCK_ID,
|
|
362
|
+
st as CURRENCY_CONTROL_ID,
|
|
363
|
+
I as CurrencyControl,
|
|
364
|
+
ct as FILTERS_CONTROL_ID,
|
|
365
|
+
R as FiltersControl,
|
|
366
|
+
ut as LAYOUT_ORIENTATION_CONTROL_ID,
|
|
367
|
+
mt as LOCALE_CONTROL_ID,
|
|
368
|
+
T as LayoutOrientationControl,
|
|
369
369
|
b as LocaleControl,
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
370
|
+
ft as PRICE_PLACEMENT_CONTROL_ID,
|
|
371
|
+
gt as PRODUCT_COUNT_CONTROL_ID,
|
|
372
|
+
yt as PRODUCT_LAYOUT_CONTROL_ID,
|
|
373
|
+
O as PricePlacementControl,
|
|
374
|
+
S as ProductCountControl,
|
|
375
375
|
P as ProductLayoutControl,
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
376
|
+
et as RecommendationBlockControl,
|
|
377
|
+
_t as SHUFFLE_CONTROL_ID,
|
|
378
|
+
Rt as STRATEGY_CONTROL_ID,
|
|
379
|
+
L as ShuffleControl,
|
|
380
|
+
k as StrategyControl,
|
|
381
|
+
bt as adjustProductsToSize,
|
|
382
|
+
Ot as formatProductPrice,
|
|
383
|
+
E as getBlockElement,
|
|
384
|
+
St as getCardComposition,
|
|
385
|
+
Pt as getCurrentLayout,
|
|
386
|
+
v as isPartnerManagedBlock,
|
|
387
|
+
Lt as regenerateMobileProductRows,
|
|
388
|
+
w as regenerateProductRowsWithStyles,
|
|
389
|
+
D as setCurrencyAttributes,
|
|
390
|
+
kt as updatePricesInPlace,
|
|
391
|
+
A as updateProductContentInPlace,
|
|
392
|
+
Dt as updateSingleProductContent
|
|
391
393
|
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
var g = Object.defineProperty;
|
|
2
|
+
var d = (r, s, t) => s in r ? g(r, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[s] = t;
|
|
3
|
+
var o = (r, s, t) => d(r, typeof s != "symbol" ? s + "" : s, t);
|
|
4
|
+
import { ACADEMY_LINKS as l } from "../../../../../enums/academy.js";
|
|
5
|
+
import { CommonControl as y } from "../../../common-control.js";
|
|
6
|
+
import { useRecommendationExtensionStore as h } from "../../store/recommendation.js";
|
|
7
|
+
const m = "recommendation-strategy-control";
|
|
8
|
+
class f extends y {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
o(this, "store", h());
|
|
12
|
+
o(this, "storeUnsubscription", () => {
|
|
13
|
+
});
|
|
14
|
+
o(this, "listeners", []);
|
|
15
|
+
}
|
|
16
|
+
getId() {
|
|
17
|
+
return m;
|
|
18
|
+
}
|
|
19
|
+
getTemplate() {
|
|
20
|
+
const t = this.api.translate(
|
|
21
|
+
"You can assign a recommendation strategy by selecting an existing one or creating a new one to show specific content."
|
|
22
|
+
), e = this.api.translate("For more information, you can"), a = this.api.translate("visit Academy");
|
|
23
|
+
return `
|
|
24
|
+
<div class="strategy-control-container">
|
|
25
|
+
<!-- A section heading, not a field label: the ue-label element renders
|
|
26
|
+
the panel's 13px field styling and the design asks for a 16px/600
|
|
27
|
+
heading. Kept outside a .container so the editor draws no rule. -->
|
|
28
|
+
<div class="strategy-control-header">
|
|
29
|
+
<h3 class="strategy-control-title">${this.api.translate("Recommendation Strategy")}</h3>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="strategy-control-description-row">
|
|
32
|
+
<p class="strategy-control-description">
|
|
33
|
+
${t}
|
|
34
|
+
${e}
|
|
35
|
+
<a
|
|
36
|
+
href="${l.EMAIL_RECOMMENDATION_BLOCK}"
|
|
37
|
+
target="_blank"
|
|
38
|
+
rel="noopener noreferrer">${a}</a>.
|
|
39
|
+
</p>
|
|
40
|
+
</div>
|
|
41
|
+
<div data-strategy-empty-state>
|
|
42
|
+
${this._GuTwoColumns([
|
|
43
|
+
this._GuButton({
|
|
44
|
+
name: "assignStrategy",
|
|
45
|
+
label: this.api.translate("Assign Strategy"),
|
|
46
|
+
id: "guido__btn-assign-strategy",
|
|
47
|
+
className: "strategy-control-cta accent"
|
|
48
|
+
}),
|
|
49
|
+
// Create round-trip ships in a later phase. Disabled, not dimmed:
|
|
50
|
+
// the design keeps it at full contrast.
|
|
51
|
+
this._GuButton({
|
|
52
|
+
name: "createStrategy",
|
|
53
|
+
label: this.api.translate("Create New Strategy"),
|
|
54
|
+
id: "guido__btn-create-strategy",
|
|
55
|
+
className: "strategy-control-cta primary",
|
|
56
|
+
disabled: !0
|
|
57
|
+
})
|
|
58
|
+
], "strategy-control-cta-row")}
|
|
59
|
+
</div>
|
|
60
|
+
<div data-strategy-assigned-state style="display: none;">
|
|
61
|
+
<!-- The name band bleeds to the panel edges, so it is a sibling of the
|
|
62
|
+
actions row rather than sharing its 16px inset. -->
|
|
63
|
+
<div class="strategy-control-name-band">
|
|
64
|
+
<span class="strategy-control-name" data-strategy-name></span>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="strategy-control-actions">
|
|
67
|
+
${this._strategyAction({
|
|
68
|
+
id: "guido__btn-change-strategy",
|
|
69
|
+
label: this.api.translate("Change"),
|
|
70
|
+
modifier: "change"
|
|
71
|
+
})}
|
|
72
|
+
${this._strategyAction({
|
|
73
|
+
id: "guido__btn-remove-strategy",
|
|
74
|
+
label: this.api.translate("Remove"),
|
|
75
|
+
modifier: "remove"
|
|
76
|
+
})}
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Change / Remove are icon+text actions in the design, not buttons — and
|
|
84
|
+
* `ue-button` cannot pair a caption with an arbitrary icon, so these are
|
|
85
|
+
* plain elements. Click wiring is by id, which works on any element.
|
|
86
|
+
*
|
|
87
|
+
* The icon is a CSS mask, not inline SVG: Stripo re-creates the control's
|
|
88
|
+
* markup through Angular, which rebuilds `<svg>` outside the SVG namespace
|
|
89
|
+
* (the view-box attribute comes back lowercased) and it never paints.
|
|
90
|
+
*/
|
|
91
|
+
_strategyAction({ id: t, label: e, modifier: a }) {
|
|
92
|
+
return `
|
|
93
|
+
<button
|
|
94
|
+
id="${t}"
|
|
95
|
+
type="button"
|
|
96
|
+
class="strategy-control-action strategy-control-action--${a}">
|
|
97
|
+
<span>${e}</span>
|
|
98
|
+
</button>
|
|
99
|
+
`;
|
|
100
|
+
}
|
|
101
|
+
onRender() {
|
|
102
|
+
this._teardown(), this._setupButtonListeners(), this._renderState(), this.storeUnsubscription = this.store.$subscribe(() => {
|
|
103
|
+
this._renderState();
|
|
104
|
+
}), this.store.recommendationConfigs.strategyId && !this.store.strategies.length && this.store.fetchStrategies().catch(() => {
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
onDestroy() {
|
|
108
|
+
this._teardown();
|
|
109
|
+
}
|
|
110
|
+
_teardown() {
|
|
111
|
+
this.storeUnsubscription(), this.storeUnsubscription = () => {
|
|
112
|
+
}, this.listeners.forEach(({ element: t, handler: e }) => t.removeEventListener("click", e)), this.listeners = [];
|
|
113
|
+
}
|
|
114
|
+
_setupButtonListeners() {
|
|
115
|
+
const t = this.getContainer();
|
|
116
|
+
if (!t)
|
|
117
|
+
return;
|
|
118
|
+
const e = (a, i) => {
|
|
119
|
+
const n = t.querySelector(a);
|
|
120
|
+
n && (n.addEventListener("click", i), this.listeners.push({ element: n, handler: i }));
|
|
121
|
+
};
|
|
122
|
+
e("#guido__btn-assign-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-remove-strategy", () => this.store.removeStrategy());
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Toggles empty vs assigned state from the store's current block config.
|
|
126
|
+
* Display name comes from the listing; falls back to the raw id while the
|
|
127
|
+
* listing loads (or when the strategy is no longer listed).
|
|
128
|
+
*/
|
|
129
|
+
_renderState() {
|
|
130
|
+
var c;
|
|
131
|
+
const t = this.getContainer();
|
|
132
|
+
if (!t)
|
|
133
|
+
return;
|
|
134
|
+
const e = t.querySelector("[data-strategy-empty-state]"), a = t.querySelector("[data-strategy-assigned-state]"), i = t.querySelector("[data-strategy-name]"), { strategyId: n } = this.store.recommendationConfigs;
|
|
135
|
+
!e || !a || (e.style.display = n ? "none" : "", a.style.display = n ? "" : "none", i && n && (i.textContent = ((c = this.store.assignedStrategy) == null ? void 0 : c.name) ?? `#${n}`));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export {
|
|
139
|
+
m as STRATEGY_CONTROL_ID,
|
|
140
|
+
f as StrategyControl
|
|
141
|
+
};
|