@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.
Files changed (75) hide show
  1. package/README.md +1 -0
  2. package/dist/@types/config/schemas.js +12 -6
  3. package/dist/components/Guido.vue.js +5 -5
  4. package/dist/components/Guido.vue2.js +77 -77
  5. package/dist/components/organisms/AutoSaveController.vue2.js +8 -9
  6. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +18 -0
  7. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +70 -0
  8. package/dist/components/organisms/extensions/recommendation/StrategyInfoBox.vue.js +20 -0
  9. package/dist/components/organisms/extensions/recommendation/StrategyInfoBox.vue2.js +55 -0
  10. package/dist/components/organisms/header/EditorActions.vue.js +2 -2
  11. package/dist/components/organisms/header/EditorActions.vue2.js +43 -74
  12. package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
  13. package/dist/components/organisms/header/LeftSlot.vue2.js +23 -46
  14. package/dist/components/wrappers/WpDrawer.vue.js +7 -9
  15. package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
  16. package/dist/composables/useCustomInterfaceAppearance.js +19 -16
  17. package/dist/composables/useHtmlCompiler.js +26 -37
  18. package/dist/composables/useHtmlValidator.js +0 -2
  19. package/dist/composables/useRecommendation.js +41 -34
  20. package/dist/composables/useSave.js +41 -84
  21. package/dist/composables/validators/useCouponBlockValidator.js +21 -24
  22. package/dist/composables/validators/useUnsubscribeBlockValidator.js +27 -34
  23. package/dist/config/migrator/recommendationMigrator.js +6 -4
  24. package/dist/enums/academy.js +2 -1
  25. package/dist/enums/date.js +4 -3
  26. package/dist/enums/extensions/recommendationBlock.js +25 -23
  27. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +13 -11
  28. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +96 -95
  29. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +156 -154
  30. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +141 -0
  31. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +223 -82
  32. package/dist/extensions/Blocks/common-control.js +22 -19
  33. package/dist/guido.css +1 -1
  34. package/dist/services/recommendationApi.js +78 -29
  35. package/dist/src/@types/config/schemas.d.ts +12 -0
  36. package/dist/src/components/Guido.vue.d.ts +1 -17
  37. package/dist/src/components/organisms/{validation/ValidationErrorDrawer.vue.d.ts → extensions/recommendation/AssignStrategyDrawer.vue.d.ts} +1 -0
  38. package/dist/src/components/organisms/extensions/recommendation/StrategyInfoBox.vue.d.ts +24 -0
  39. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +1 -17
  40. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -17
  41. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -17
  42. package/dist/src/components/wrappers/WpDrawer.vue.d.ts +3 -4
  43. package/dist/src/composables/useConfig.d.ts +2 -0
  44. package/dist/src/composables/useHtmlValidator.d.ts +0 -21
  45. package/dist/src/composables/useRecommendation.d.ts +1 -0
  46. package/dist/src/composables/useSave.d.ts +1 -6
  47. package/dist/src/composables/validators/useCouponBlockValidator.d.ts +0 -3
  48. package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +0 -10
  49. package/dist/src/enums/academy.d.ts +1 -0
  50. package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
  51. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +14 -3
  52. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +29 -0
  53. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +214 -15
  54. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +6 -0
  55. package/dist/src/extensions/Blocks/common-control.d.ts +4 -1
  56. package/dist/src/mock/api/recommendation-strategies.d.ts +43 -0
  57. package/dist/src/services/recommendationApi.d.ts +4 -1
  58. package/dist/src/stores/config.d.ts +18 -5
  59. package/dist/src/utils/templatePreparation.d.ts +0 -30
  60. package/dist/static/styles/components/recommendation-strategy.css.js +171 -0
  61. package/dist/stores/config.js +6 -13
  62. package/dist/utils/dateUtil.js +23 -10
  63. package/dist/utils/templatePreparation.js +50 -50
  64. package/package.json +2 -1
  65. package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +0 -20
  66. package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +0 -48
  67. package/dist/composables/useSaveValidation.js +0 -279
  68. package/dist/composables/useSaveValidationRollout.js +0 -9
  69. package/dist/enums/save-validation.js +0 -4
  70. package/dist/src/@types/save-validation.d.ts +0 -19
  71. package/dist/src/composables/useSaveValidation.d.ts +0 -6
  72. package/dist/src/composables/useSaveValidationRollout.d.ts +0 -3
  73. package/dist/src/enums/save-validation.d.ts +0 -27
  74. package/dist/src/stores/save-validation.d.ts +0 -22
  75. package/dist/stores/save-validation.js +0 -30
@@ -1,4 +1,4 @@
1
- import type { Orientation, Languages, Currency, NumericSeparator, FiltersResponse, Filter, RecommendationProduct } from '@@/Types/recommendation';
1
+ import type { Orientation, Languages, Currency, NumericSeparator, FiltersResponse, Filter, RecommendationCampaignUrlValue, RecommendationProduct, RrsStrategy } from '@@/Types/recommendation';
2
2
  export interface PerBlockConfigs {
3
3
  cardsInRow: number;
4
4
  currencySettings: {
@@ -21,6 +21,8 @@ export interface PerBlockConfigs {
21
21
  sendProductRequestFlag: boolean;
22
22
  shuffleProducts: boolean;
23
23
  strategy: string;
24
+ /** Assigned RRS id ('' = none) — mirrors RecommendationNodeConfig.strategyId (SD-149105) */
25
+ strategyId: string;
24
26
  textTrimming: boolean;
25
27
  unresponsive: boolean;
26
28
  size: string;
@@ -33,6 +35,8 @@ interface PerBlockState {
33
35
  recommendationProducts: RecommendationProduct[];
34
36
  filterStatus: boolean;
35
37
  filterSelectionDrawerStatus: boolean;
38
+ /** Assign Recommendation Strategy drawer visibility (SD-149105) */
39
+ assignStrategyDrawerStatus: boolean;
36
40
  filterGroup: number;
37
41
  /** Whether initial API data (filters, algorithms, products) has been fetched for this block */
38
42
  isInitialized: boolean;
@@ -47,6 +51,7 @@ interface PerBlockState {
47
51
  */
48
52
  export interface PerBlockUrlConfig {
49
53
  strategy: string;
54
+ strategyId: string;
50
55
  language: string;
51
56
  size: string;
52
57
  productIds: string[];
@@ -59,11 +64,14 @@ export interface PerBlockUrlConfig {
59
64
  currencyThousandSeparator: string;
60
65
  }
61
66
  interface StoreState {
62
- recommendationCampaignUrls: Record<string, string>;
67
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
63
68
  activePredictiveAlgorithms: number[];
64
69
  languages: Languages;
65
70
  currencyList: Currency[];
66
71
  filterList: FiltersResponse;
72
+ strategies: RrsStrategy[];
73
+ strategiesLoading: boolean;
74
+ strategyUrlTemplates: Record<string, string>;
67
75
  blockStates: Record<number, PerBlockState>;
68
76
  currentRecommendationId: number | null;
69
77
  configVersion: number;
@@ -74,7 +82,7 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
74
82
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
75
83
  */
76
84
  recommendationConfigs(state: {
77
- recommendationCampaignUrls: Record<string, string>;
85
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
78
86
  activePredictiveAlgorithms: number[];
79
87
  languages: Languages;
80
88
  currencyList: {
@@ -82,6 +90,16 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
82
90
  value: string;
83
91
  }[];
84
92
  filterList: FiltersResponse;
93
+ strategies: {
94
+ [x: string]: unknown;
95
+ strategy_id: number;
96
+ name: string;
97
+ status: string;
98
+ suitable_channels: string;
99
+ size?: (number | string) | undefined;
100
+ }[];
101
+ strategiesLoading: boolean;
102
+ strategyUrlTemplates: Record<string, string>;
85
103
  blockStates: Record<number, PerBlockState>;
86
104
  currentRecommendationId: number | null;
87
105
  configVersion: number;
@@ -90,7 +108,7 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
90
108
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
91
109
  */
92
110
  recommendationProducts(state: {
93
- recommendationCampaignUrls: Record<string, string>;
111
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
94
112
  activePredictiveAlgorithms: number[];
95
113
  languages: Languages;
96
114
  currencyList: {
@@ -98,6 +116,16 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
98
116
  value: string;
99
117
  }[];
100
118
  filterList: FiltersResponse;
119
+ strategies: {
120
+ [x: string]: unknown;
121
+ strategy_id: number;
122
+ name: string;
123
+ status: string;
124
+ suitable_channels: string;
125
+ size?: (number | string) | undefined;
126
+ }[];
127
+ strategiesLoading: boolean;
128
+ strategyUrlTemplates: Record<string, string>;
101
129
  blockStates: Record<number, PerBlockState>;
102
130
  currentRecommendationId: number | null;
103
131
  configVersion: number;
@@ -106,7 +134,7 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
106
134
  * Proxy getter: delegates to blockStates[currentRecommendationId].filterSelectionDrawerStatus
107
135
  */
108
136
  filterSelectionDrawerStatus(state: {
109
- recommendationCampaignUrls: Record<string, string>;
137
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
110
138
  activePredictiveAlgorithms: number[];
111
139
  languages: Languages;
112
140
  currencyList: {
@@ -114,15 +142,78 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
114
142
  value: string;
115
143
  }[];
116
144
  filterList: FiltersResponse;
145
+ strategies: {
146
+ [x: string]: unknown;
147
+ strategy_id: number;
148
+ name: string;
149
+ status: string;
150
+ suitable_channels: string;
151
+ size?: (number | string) | undefined;
152
+ }[];
153
+ strategiesLoading: boolean;
154
+ strategyUrlTemplates: Record<string, string>;
117
155
  blockStates: Record<number, PerBlockState>;
118
156
  currentRecommendationId: number | null;
119
157
  configVersion: number;
120
158
  } & import("pinia").PiniaCustomStateProperties<StoreState>): boolean;
159
+ /**
160
+ * Proxy getter: delegates to blockStates[currentRecommendationId].assignStrategyDrawerStatus
161
+ */
162
+ assignStrategyDrawerStatus(state: {
163
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
164
+ activePredictiveAlgorithms: number[];
165
+ languages: Languages;
166
+ currencyList: {
167
+ text: string;
168
+ value: string;
169
+ }[];
170
+ filterList: FiltersResponse;
171
+ strategies: {
172
+ [x: string]: unknown;
173
+ strategy_id: number;
174
+ name: string;
175
+ status: string;
176
+ suitable_channels: string;
177
+ size?: (number | string) | undefined;
178
+ }[];
179
+ strategiesLoading: boolean;
180
+ strategyUrlTemplates: Record<string, string>;
181
+ blockStates: Record<number, PerBlockState>;
182
+ currentRecommendationId: number | null;
183
+ configVersion: number;
184
+ } & import("pinia").PiniaCustomStateProperties<StoreState>): boolean;
185
+ /**
186
+ * The current block's assigned strategy record from the listing,
187
+ * or null when nothing is assigned / the strategy is no longer listed.
188
+ */
189
+ assignedStrategy(state: {
190
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
191
+ activePredictiveAlgorithms: number[];
192
+ languages: Languages;
193
+ currencyList: {
194
+ text: string;
195
+ value: string;
196
+ }[];
197
+ filterList: FiltersResponse;
198
+ strategies: {
199
+ [x: string]: unknown;
200
+ strategy_id: number;
201
+ name: string;
202
+ status: string;
203
+ suitable_channels: string;
204
+ size?: (number | string) | undefined;
205
+ }[];
206
+ strategiesLoading: boolean;
207
+ strategyUrlTemplates: Record<string, string>;
208
+ blockStates: Record<number, PerBlockState>;
209
+ currentRecommendationId: number | null;
210
+ configVersion: number;
211
+ } & import("pinia").PiniaCustomStateProperties<StoreState>): RrsStrategy | null;
121
212
  /**
122
213
  * Proxy getter: delegates to blockStates[currentRecommendationId].filterStatus
123
214
  */
124
215
  filterStatus(state: {
125
- recommendationCampaignUrls: Record<string, string>;
216
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
126
217
  activePredictiveAlgorithms: number[];
127
218
  languages: Languages;
128
219
  currencyList: {
@@ -130,6 +221,16 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
130
221
  value: string;
131
222
  }[];
132
223
  filterList: FiltersResponse;
224
+ strategies: {
225
+ [x: string]: unknown;
226
+ strategy_id: number;
227
+ name: string;
228
+ status: string;
229
+ suitable_channels: string;
230
+ size?: (number | string) | undefined;
231
+ }[];
232
+ strategiesLoading: boolean;
233
+ strategyUrlTemplates: Record<string, string>;
133
234
  blockStates: Record<number, PerBlockState>;
134
235
  currentRecommendationId: number | null;
135
236
  configVersion: number;
@@ -138,7 +239,7 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
138
239
  * Proxy getter: delegates to blockStates[currentRecommendationId].filterGroup
139
240
  */
140
241
  filterGroup(state: {
141
- recommendationCampaignUrls: Record<string, string>;
242
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
142
243
  activePredictiveAlgorithms: number[];
143
244
  languages: Languages;
144
245
  currencyList: {
@@ -146,6 +247,16 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
146
247
  value: string;
147
248
  }[];
148
249
  filterList: FiltersResponse;
250
+ strategies: {
251
+ [x: string]: unknown;
252
+ strategy_id: number;
253
+ name: string;
254
+ status: string;
255
+ suitable_channels: string;
256
+ size?: (number | string) | undefined;
257
+ }[];
258
+ strategiesLoading: boolean;
259
+ strategyUrlTemplates: Record<string, string>;
149
260
  blockStates: Record<number, PerBlockState>;
150
261
  currentRecommendationId: number | null;
151
262
  configVersion: number;
@@ -155,7 +266,7 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
155
266
  getFilterGroupCount(): number;
156
267
  getUniqueFilterGroups(): number[];
157
268
  getActivePredictiveAlgorithms: (state: {
158
- recommendationCampaignUrls: Record<string, string>;
269
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
159
270
  activePredictiveAlgorithms: number[];
160
271
  languages: Languages;
161
272
  currencyList: {
@@ -163,6 +274,16 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
163
274
  value: string;
164
275
  }[];
165
276
  filterList: FiltersResponse;
277
+ strategies: {
278
+ [x: string]: unknown;
279
+ strategy_id: number;
280
+ name: string;
281
+ status: string;
282
+ suitable_channels: string;
283
+ size?: (number | string) | undefined;
284
+ }[];
285
+ strategiesLoading: boolean;
286
+ strategyUrlTemplates: Record<string, string>;
166
287
  blockStates: Record<number, PerBlockState>;
167
288
  currentRecommendationId: number | null;
168
289
  configVersion: number;
@@ -171,7 +292,7 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
171
292
  value: string;
172
293
  }[];
173
294
  getLanguages: (state: {
174
- recommendationCampaignUrls: Record<string, string>;
295
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
175
296
  activePredictiveAlgorithms: number[];
176
297
  languages: Languages;
177
298
  currencyList: {
@@ -179,6 +300,16 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
179
300
  value: string;
180
301
  }[];
181
302
  filterList: FiltersResponse;
303
+ strategies: {
304
+ [x: string]: unknown;
305
+ strategy_id: number;
306
+ name: string;
307
+ status: string;
308
+ suitable_channels: string;
309
+ size?: (number | string) | undefined;
310
+ }[];
311
+ strategiesLoading: boolean;
312
+ strategyUrlTemplates: Record<string, string>;
182
313
  blockStates: Record<number, PerBlockState>;
183
314
  currentRecommendationId: number | null;
184
315
  configVersion: number;
@@ -187,7 +318,7 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
187
318
  value: string;
188
319
  }[];
189
320
  getCurrencySymbolList: (state: {
190
- recommendationCampaignUrls: Record<string, string>;
321
+ recommendationCampaignUrls: Record<string, RecommendationCampaignUrlValue>;
191
322
  activePredictiveAlgorithms: number[];
192
323
  languages: Languages;
193
324
  currencyList: {
@@ -195,6 +326,16 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
195
326
  value: string;
196
327
  }[];
197
328
  filterList: FiltersResponse;
329
+ strategies: {
330
+ [x: string]: unknown;
331
+ strategy_id: number;
332
+ name: string;
333
+ status: string;
334
+ suitable_channels: string;
335
+ size?: (number | string) | undefined;
336
+ }[];
337
+ strategiesLoading: boolean;
338
+ strategyUrlTemplates: Record<string, string>;
198
339
  blockStates: Record<number, PerBlockState>;
199
340
  currentRecommendationId: number | null;
200
341
  configVersion: number;
@@ -272,6 +413,52 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
272
413
  * to the snapshot taken when the drawer was opened.
273
414
  */
274
415
  cancelFilterDrawer(): void;
416
+ /**
417
+ * Opens the Assign Strategy drawer for the current block.
418
+ * Selection state lives in the drawer component until Assign is
419
+ * pressed, so closing without assigning needs no snapshot/revert.
420
+ */
421
+ openAssignStrategyDrawer(): void;
422
+ closeAssignStrategyDrawer(): void;
423
+ /**
424
+ * Fetches the active + EMAIL strategy listing. Always fetches fresh
425
+ * (dead-strategy detection and post-create refresh need freshness);
426
+ * only concurrent in-flight calls share one request.
427
+ */
428
+ fetchStrategies(): Promise<void>;
429
+ /**
430
+ * Resolves a strategy's recommendation endpoint template via
431
+ * endpoint-generate, cached per strategy id + revision. Failures throw
432
+ * and are NOT cached, so the next attempt retries.
433
+ *
434
+ * The revision is part of the key because `full_path` bakes in the
435
+ * algorithm path and `size=` as they were when it was generated, while
436
+ * the listing is deliberately never cached — editing a strategy in the
437
+ * panel and re-assigning it here would otherwise call a stale endpoint.
438
+ *
439
+ * A record with no revision is not cached at all: a `<id>:` key can
440
+ * never change, so it would serve the stale template forever — exactly
441
+ * what the revision is here to prevent.
442
+ */
443
+ resolveStrategyUrlTemplate(strategy: RrsStrategy): Promise<string>;
444
+ /**
445
+ * Assigns a strategy to the current block. The config write is
446
+ * synchronous (before any await) so a block switch cannot misdirect
447
+ * it; the configVersion bump persists it to node config and triggers
448
+ * the product refetch via the coordinator control's subscription.
449
+ */
450
+ assignStrategy(strategy: RrsStrategy): void;
451
+ /**
452
+ * Clears the current block's strategy; it falls back to the per-block
453
+ * algorithm settings.
454
+ *
455
+ * `size` goes back to the default rather than staying on the removed
456
+ * strategy's count: the Number of Products control is hidden in RRS
457
+ * mode (D2), so a block left on the strategy's count would have no UI
458
+ * to correct it. The pre-assign count is not restored — that would
459
+ * need a persisted snapshot field; tracked for a later phase.
460
+ */
461
+ removeStrategy(): void;
275
462
  fetchRecommendationCreateData(): Promise<void>;
276
463
  fetchRecommendationFilters(): Promise<void>;
277
464
  addFilterGroup(filterGroup: number): void;
@@ -286,12 +473,24 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
286
473
  * every block's recommendationConfigs across user edits.
287
474
  */
288
475
  hasInvalidBlock(): boolean;
289
- /**
290
- * Per-instance counterpart to `hasInvalidBlock`: the ids of every block
291
- * that fails required-field validation, one drawer row each (SD-147430).
292
- */
293
- invalidBlockIds(): string[];
294
476
  fetchRecommendationProducts(): Promise<void>;
295
477
  _doFetchProducts(): Promise<void>;
478
+ /**
479
+ * Fetches products for a strategy-backed block: listing lookup →
480
+ * endpoint-generate template → fill {locale}/{currency}, drop
481
+ * {user_id} (resolved at send time) → fetch. Any failure (dead
482
+ * strategy, resolution error) falls back to placeholder products.
483
+ */
484
+ _doFetchStrategyProducts(blockId: number): Promise<void>;
485
+ /**
486
+ * Writes products to a block's state, padded/clipped to `size` so
487
+ * in-place content updates (which compare DOM element count vs
488
+ * products.length) succeed:
489
+ * - API returned nothing → fill entirely with defaults
490
+ * - fewer than requested → pad with dummies
491
+ * - more than requested → clip, preventing the renderer from extending
492
+ * its slot grid (which would reset migrator-applied styles).
493
+ */
494
+ _setBlockProducts(blockId: number, products: RecommendationProduct[], size: number): void;
296
495
  }>;
297
496
  export {};
@@ -82,6 +82,12 @@ export interface RecommendationNodeConfig {
82
82
  * Uses existing Filter interface from recommendation types
83
83
  */
84
84
  filters: Filter[];
85
+ /**
86
+ * Assigned Reusable Recommendation Strategy id (SD-149105).
87
+ * '' = no strategy assigned; block uses the per-block settings above.
88
+ * When set, algorithm/size/filters/shuffle come from the strategy record.
89
+ */
90
+ strategyId: string;
85
91
  /**
86
92
  * Layout orientation
87
93
  * - 'grid': Products in a grid, attributes aligned across products
@@ -56,6 +56,9 @@ interface ButtonProps {
56
56
  name: string;
57
57
  label: string;
58
58
  id?: string;
59
+ className?: string;
60
+ icon?: string;
61
+ disabled?: boolean;
59
62
  }
60
63
  /**
61
64
  * Common control for all blocks which includes common UI Elements.
@@ -116,7 +119,7 @@ export declare abstract class CommonControl extends Control {
116
119
  icon?: string;
117
120
  }): string;
118
121
  _GuRadioButton({ name, buttons, id }: RadioButtonProps): string;
119
- _GuButton({ name, label, id }: ButtonProps): string;
122
+ _GuButton({ name, label, id, className, icon, disabled }: ButtonProps): string;
120
123
  _GuIcon({ src, className }: IconProps): string;
121
124
  /**
122
125
  *
@@ -0,0 +1,43 @@
1
+ export declare const MOCK_RRS_STRATEGIES: ({
2
+ strategy_id: number;
3
+ name: string;
4
+ status: string;
5
+ suitable_channels: string;
6
+ suitable_page_types: string;
7
+ algorithm: string;
8
+ algorithm_used: string;
9
+ size: number;
10
+ filters: string;
11
+ shuffle: number;
12
+ attribute_affinity: number;
13
+ exclude_view: number;
14
+ exclude_purchase: number;
15
+ created_at: string;
16
+ updated_at: string;
17
+ last_updated_by: string;
18
+ mixed_strategies?: undefined;
19
+ exclude_view_duration?: undefined;
20
+ exclude_view_duration_type?: undefined;
21
+ } | {
22
+ strategy_id: number;
23
+ name: string;
24
+ status: string;
25
+ suitable_channels: string;
26
+ suitable_page_types: string;
27
+ algorithm: string;
28
+ algorithm_used: string;
29
+ mixed_strategies: string;
30
+ size: number;
31
+ filters: string;
32
+ shuffle: number;
33
+ attribute_affinity: number;
34
+ exclude_view: number;
35
+ exclude_view_duration: number;
36
+ exclude_view_duration_type: string;
37
+ exclude_purchase: number;
38
+ created_at: string;
39
+ updated_at: string;
40
+ last_updated_by: string;
41
+ })[];
42
+ declare const _default: import("msw").HttpHandler[];
43
+ export default _default;
@@ -1,6 +1,9 @@
1
- import type { InitialResponse, FiltersResponse, RecommendationProduct, RecommendationProductsParams } from '@@/Types/recommendation';
1
+ import type { InitialResponse, FiltersResponse, RecommendationProduct, RecommendationProductsParams, RrsEndpointGenerateResponse, RrsStrategy } from '@@/Types/recommendation';
2
2
  export declare const useRecommendationApi: () => {
3
3
  fetchRecommendationCreateData: () => Promise<InitialResponse>;
4
4
  fetchRecommendationFilters: () => Promise<FiltersResponse>;
5
5
  fetchRecommendationProducts: (strategy: string, params: RecommendationProductsParams) => Promise<RecommendationProduct[]>;
6
+ fetchRecommendationProductsByUrl: (url: string) => Promise<RecommendationProduct[]>;
7
+ fetchRecommendationStrategies: () => Promise<RrsStrategy[]>;
8
+ generateStrategyEndpoint: (strategy: RrsStrategy) => Promise<RrsEndpointGenerateResponse>;
6
9
  };
@@ -104,6 +104,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
104
104
  autosave: boolean;
105
105
  allowlistEnabled: boolean;
106
106
  linkTrackingIds: boolean;
107
+ reusableRecommendationStrategy: boolean;
107
108
  };
108
109
  blocks: {
109
110
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -244,6 +245,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
244
245
  autosave: boolean;
245
246
  allowlistEnabled: boolean;
246
247
  linkTrackingIds: boolean;
248
+ reusableRecommendationStrategy: boolean;
247
249
  };
248
250
  blocks: {
249
251
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -384,6 +386,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
384
386
  autosave: boolean;
385
387
  allowlistEnabled: boolean;
386
388
  linkTrackingIds: boolean;
389
+ reusableRecommendationStrategy: boolean;
387
390
  };
388
391
  blocks: {
389
392
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -524,6 +527,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
524
527
  autosave: boolean;
525
528
  allowlistEnabled: boolean;
526
529
  linkTrackingIds: boolean;
530
+ reusableRecommendationStrategy: boolean;
527
531
  };
528
532
  blocks: {
529
533
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -664,6 +668,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
664
668
  autosave: boolean;
665
669
  allowlistEnabled: boolean;
666
670
  linkTrackingIds: boolean;
671
+ reusableRecommendationStrategy: boolean;
667
672
  };
668
673
  blocks: {
669
674
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -804,6 +809,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
804
809
  autosave: boolean;
805
810
  allowlistEnabled: boolean;
806
811
  linkTrackingIds: boolean;
812
+ reusableRecommendationStrategy: boolean;
807
813
  };
808
814
  blocks: {
809
815
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -944,6 +950,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
944
950
  autosave: boolean;
945
951
  allowlistEnabled: boolean;
946
952
  linkTrackingIds: boolean;
953
+ reusableRecommendationStrategy: boolean;
947
954
  };
948
955
  blocks: {
949
956
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1084,6 +1091,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1084
1091
  autosave: boolean;
1085
1092
  allowlistEnabled: boolean;
1086
1093
  linkTrackingIds: boolean;
1094
+ reusableRecommendationStrategy: boolean;
1087
1095
  };
1088
1096
  blocks: {
1089
1097
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1224,6 +1232,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1224
1232
  autosave: boolean;
1225
1233
  allowlistEnabled: boolean;
1226
1234
  linkTrackingIds: boolean;
1235
+ reusableRecommendationStrategy: boolean;
1227
1236
  };
1228
1237
  blocks: {
1229
1238
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1364,6 +1373,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1364
1373
  autosave: boolean;
1365
1374
  allowlistEnabled: boolean;
1366
1375
  linkTrackingIds: boolean;
1376
+ reusableRecommendationStrategy: boolean;
1367
1377
  };
1368
1378
  blocks: {
1369
1379
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1504,6 +1514,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1504
1514
  autosave: boolean;
1505
1515
  allowlistEnabled: boolean;
1506
1516
  linkTrackingIds: boolean;
1517
+ reusableRecommendationStrategy: boolean;
1507
1518
  };
1508
1519
  blocks: {
1509
1520
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1644,6 +1655,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1644
1655
  autosave: boolean;
1645
1656
  allowlistEnabled: boolean;
1646
1657
  linkTrackingIds: boolean;
1658
+ reusableRecommendationStrategy: boolean;
1647
1659
  };
1648
1660
  blocks: {
1649
1661
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1784,6 +1796,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1784
1796
  autosave: boolean;
1785
1797
  allowlistEnabled: boolean;
1786
1798
  linkTrackingIds: boolean;
1799
+ reusableRecommendationStrategy: boolean;
1787
1800
  };
1788
1801
  blocks: {
1789
1802
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1924,6 +1937,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1924
1937
  autosave: boolean;
1925
1938
  allowlistEnabled: boolean;
1926
1939
  linkTrackingIds: boolean;
1940
+ reusableRecommendationStrategy: boolean;
1927
1941
  };
1928
1942
  blocks: {
1929
1943
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2064,6 +2078,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2064
2078
  autosave: boolean;
2065
2079
  allowlistEnabled: boolean;
2066
2080
  linkTrackingIds: boolean;
2081
+ reusableRecommendationStrategy: boolean;
2067
2082
  };
2068
2083
  blocks: {
2069
2084
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2106,11 +2121,6 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2106
2121
  };
2107
2122
  } | null;
2108
2123
  } & import("pinia").PiniaCustomStateProperties<ConfigStoreState>) => number;
2109
- /**
2110
- * Transactional campaigns keep the hard save block. Reactive getter, so
2111
- * consumers stay safe in setup where a raw config read snapshots null (SD-147945).
2112
- */
2113
- isTransactional(): boolean;
2114
2124
  /**
2115
2125
  * Get the username
2116
2126
  */
@@ -2209,6 +2219,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2209
2219
  autosave: boolean;
2210
2220
  allowlistEnabled: boolean;
2211
2221
  linkTrackingIds: boolean;
2222
+ reusableRecommendationStrategy: boolean;
2212
2223
  };
2213
2224
  blocks: {
2214
2225
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2349,6 +2360,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2349
2360
  autosave: boolean;
2350
2361
  allowlistEnabled: boolean;
2351
2362
  linkTrackingIds: boolean;
2363
+ reusableRecommendationStrategy: boolean;
2352
2364
  };
2353
2365
  blocks: {
2354
2366
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2491,6 +2503,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2491
2503
  autosave: boolean;
2492
2504
  allowlistEnabled: boolean;
2493
2505
  linkTrackingIds: boolean;
2506
+ reusableRecommendationStrategy: boolean;
2494
2507
  };
2495
2508
  blocks: {
2496
2509
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -15,36 +15,6 @@ import type { SavedTemplateDetails } from '@@/Types/stripo';
15
15
  * same source), so it is reliably present regardless of how the block was added.
16
16
  */
17
17
  export declare function getHtmlReferencedUnsubscribePages(html: string): number[];
18
- /**
19
- * Hydrates the recommendation extension store from the persisted `esd-ext-config`
20
- * JSON blob on each `.recommendation-block-v2` element in the raw editor HTML.
21
- *
22
- * Why this runs before `compileHtml`:
23
- * The HTML compiler's `prepareRecommendationBlocks` rule asks
24
- * `useRecommendation.buildCampaignUrl(id)` to assemble each block's API URL
25
- * from `blockStates[id].recommendationConfigs`. That Pinia entry is normally
26
- * populated by `RecommendationBlockControl._syncNodeConfigToStore`, which
27
- * only fires when the user *selects* the block. Saving without ever
28
- * selecting a migrated block would otherwise build the URL from empty/
29
- * default state and the campaign URL would not be saved.
30
- *
31
- * Why we read raw HTML, not compiled HTML:
32
- * Stripo's `compileEmail()` strips editor-only attributes (`esd-*`) from the
33
- * compiled output, so `esd-ext-config` is gone by the time the compiler
34
- * pipeline sees the HTML. The raw HTML from `getTemplateData()` preserves
35
- * the attribute as the migrator wrote it.
36
- *
37
- * Reference data pre-load:
38
- * When the template has recommendation blocks, this also pre-loads the
39
- * shared reference data (languages / currency list) so the save-time
40
- * required-fields validator can check each block's locale and currency
41
- * against the partner's real options. Best-effort — on a fetch failure the
42
- * validator degrades to its empty-list guard (`requiredFields.ts`) instead
43
- * of blocking the save or stranding the Save button.
44
- */
45
- declare function hydrateRecommendationStoreFromRawHtml(rawHtml: string): Promise<void>;
46
18
  export declare const useTemplatePreparation: () => {
47
19
  prepareTemplateDetails: () => Promise<Omit<SavedTemplateDetails, "metadata">>;
48
- hydrateRecommendationStore: typeof hydrateRecommendationStoreFromRawHtml;
49
20
  };
50
- export {};