@useinsider/guido 3.19.0-beta.f02eaa1 → 3.19.0-beta.f0d5980

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 (72) hide show
  1. package/dist/@types/config/schemas.js +104 -91
  2. package/dist/components/Guido.vue.js +8 -8
  3. package/dist/components/Guido.vue2.js +86 -81
  4. package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
  5. package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
  6. package/dist/components/organisms/base/Toaster.vue2.js +13 -12
  7. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +9 -7
  8. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +69 -52
  9. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +28 -44
  10. package/dist/components/organisms/header/EditorActions.vue.js +4 -4
  11. package/dist/components/organisms/header/EditorActions.vue2.js +23 -25
  12. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +3 -3
  13. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +21 -20
  14. package/dist/components/wrappers/WpModal.vue.js +1 -1
  15. package/dist/components/wrappers/WpModal.vue2.js +4 -3
  16. package/dist/composables/useActionsApi.js +52 -47
  17. package/dist/composables/useAuthError.js +52 -0
  18. package/dist/composables/useCodeEditorApi.js +23 -9
  19. package/dist/composables/useCustomInterfaceAppearance.js +61 -51
  20. package/dist/composables/useHtmlValidator.js +87 -82
  21. package/dist/composables/useHttp.js +64 -54
  22. package/dist/composables/useLegacyStrategyConversion.js +23 -19
  23. package/dist/composables/useRecommendation.js +40 -35
  24. package/dist/composables/useStripo.js +43 -39
  25. package/dist/composables/useToaster.js +18 -22
  26. package/dist/composables/useTranslations.js +3 -2
  27. package/dist/composables/useVersionHistoryApi.js +33 -24
  28. package/dist/composables/validators/useLiquidValidator.js +15 -15
  29. package/dist/config/migrator/index.js +14 -13
  30. package/dist/config/migrator/recommendationPartnerMigrator.js +50 -0
  31. package/dist/enums/extensions/recommendationBlock.js +43 -35
  32. package/dist/extensions/Blocks/Recommendation/block.js +65 -45
  33. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +21 -20
  34. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +70 -58
  35. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +133 -79
  36. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +96 -97
  37. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +212 -94
  38. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js +1 -1
  39. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +26 -16
  40. package/dist/extensions/Blocks/Recommendation/utils/partnerScope.js +25 -0
  41. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +24 -0
  42. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +21 -12
  43. package/dist/guido.css +1 -1
  44. package/dist/src/@types/config/schemas.d.ts +16 -0
  45. package/dist/src/components/organisms/base/AuthErrorModal.vue.d.ts +2 -0
  46. package/dist/src/components/wrappers/WpModal.vue.d.ts +5 -1
  47. package/dist/src/composables/useAuthError.d.ts +12 -0
  48. package/dist/src/composables/useConfig.d.ts +2 -0
  49. package/dist/src/composables/useHttp.d.ts +2 -0
  50. package/dist/src/config/migrator/index.d.ts +2 -1
  51. package/dist/src/config/migrator/recommendationPartnerMigrator.d.ts +19 -0
  52. package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
  53. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +10 -0
  54. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +1 -0
  55. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  56. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +2 -0
  57. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +8 -0
  58. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +7 -6
  59. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +92 -0
  60. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +6 -0
  61. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.d.ts +1 -1
  62. package/dist/src/extensions/Blocks/Recommendation/utils/partnerScope.d.ts +33 -0
  63. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +14 -0
  64. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +4 -0
  65. package/dist/src/stores/config.d.ts +20 -0
  66. package/dist/src/utils/stripoEditorApi.d.ts +4 -0
  67. package/dist/static/styles/components/recommendation-strategy.css.js +43 -4
  68. package/dist/static/styles/components/skeleton.css.js +23 -0
  69. package/dist/stores/unsubscribe.js +3 -3
  70. package/dist/utils/stripoEditorApi.js +11 -0
  71. package/dist/utils/templatePreparation.js +55 -55
  72. package/package.json +2 -1
@@ -1,10 +1,10 @@
1
- var m = Object.defineProperty;
2
- var C = (g, l, t) => l in g ? m(g, l, { enumerable: !0, configurable: !0, writable: !0, value: t }) : g[l] = t;
3
- var r = (g, l, t) => C(g, typeof l != "symbol" ? l + "" : l, t);
4
- import { useConfig as p } from "../../../../../composables/useConfig.js";
1
+ var C = Object.defineProperty;
2
+ var p = (g, u, t) => u in g ? C(g, u, { enumerable: !0, configurable: !0, writable: !0, value: t }) : g[u] = t;
3
+ var i = (g, u, t) => p(g, typeof u != "symbol" ? u + "" : u, t);
4
+ import { useConfig as h } from "../../../../../composables/useConfig.js";
5
5
  import { ModificationDescription as y } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
6
6
  import { CommonControl as N } from "../../../common-control.js";
7
- import { CURRENT_CONFIG_VERSION as _, DEFAULT_NODE_CONFIG as a } from "../../constants/defaultConfig.js";
7
+ import { RRS_CONFIG_VERSION as _, DEFAULT_NODE_CONFIG as a } from "../../constants/defaultConfig.js";
8
8
  import { RECOMMENDATION_ID_ATTR as I } from "../../constants/selectors.js";
9
9
  import { RecommendationConfigService as c } from "../../services/configService.js";
10
10
  import { useRecommendationExtensionStore as R } from "../../store/recommendation.js";
@@ -14,7 +14,7 @@ import { ALGORITHM_CONTROL_ID as ut } from "./algorithm.js";
14
14
  import { CurrencyControl as P } from "./currency.js";
15
15
  import { CURRENCY_CONTROL_ID as gt } from "./currency.js";
16
16
  import { FiltersControl as S } from "./filters.js";
17
- import { FILTERS_CONTROL_ID as ht } from "./filters.js";
17
+ import { FILTERS_CONTROL_ID as ft } from "./filters.js";
18
18
  import { LayoutOrientationControl as O } from "./layoutOrientation.js";
19
19
  import { LAYOUT_ORIENTATION_CONTROL_ID as Ct } from "./layoutOrientation.js";
20
20
  import { LocaleControl as L } from "./locale.js";
@@ -29,36 +29,36 @@ import { ShuffleControl as D } from "./shuffle.js";
29
29
  import { SHUFFLE_CONTROL_ID as St } from "./shuffle.js";
30
30
  import { StrategyControl as w } from "./strategy.js";
31
31
  import { STRATEGY_CONTROL_ID as Lt } from "./strategy.js";
32
- import { setCurrencyAttributes as A, getBlockElement as B, isPartnerManagedBlock as v, updateProductContentInPlace as x, regenerateProductRowsWithStyles as U } from "./utils.js";
33
- import { adjustProductsToSize as Et, formatProductPrice as Ft, getCardComposition as Dt, getCurrentLayout as wt, getMainContainerTbody as At, regenerateMobileProductRows as Bt, updatePricesInPlace as vt, updateSingleProductContent as xt } from "./utils.js";
32
+ import { setCurrencyAttributes as v, getBlockElement as A, isPartnerManagedBlock as B, updateProductContentInPlace as x, regenerateProductRowsWithStyles as U } from "./utils.js";
33
+ import { adjustProductsToSize as Et, formatProductPrice as Ft, getCardComposition as Dt, getCurrentLayout as wt, getMainContainerTbody as vt, regenerateMobileProductRows as At, updatePricesInPlace as Bt, updateSingleProductContent as xt } from "./utils.js";
34
34
  import { useDebounceFn as f } from "../../../../../node_modules/@vueuse/shared/index.js";
35
- const $ = "ui-elements-recommendation-block";
35
+ const W = "ui-elements-recommendation-block";
36
36
  class at extends N {
37
37
  constructor() {
38
38
  super(...arguments);
39
- r(this, "store", R());
40
- r(this, "storeUnsubscription", () => {
39
+ i(this, "store", R());
40
+ i(this, "storeUnsubscription", () => {
41
41
  });
42
42
  // A config change waiting to reach the node config. Deferred so it can ride the
43
43
  // re-render's single apply() — one user action must cost one undo press.
44
- r(this, "pendingNodeConfigWrite", null);
45
- r(this, "pendingConfigFlushTimer", null);
44
+ i(this, "pendingNodeConfigWrite", null);
45
+ i(this, "pendingConfigFlushTimer", null);
46
46
  // Sub-control instances for lifecycle management
47
- r(this, "algorithmControl", null);
48
- r(this, "localeControl", null);
49
- r(this, "currencyControl", null);
50
- r(this, "productCountControl", null);
51
- r(this, "productLayoutControl", null);
52
- r(this, "filtersControl", null);
53
- r(this, "shuffleControl", null);
54
- r(this, "pricePlacementControl", null);
55
- r(this, "layoutOrientationControl", null);
56
- r(this, "strategyControl", null);
57
- r(this, "rrsEnabled", !1);
47
+ i(this, "algorithmControl", null);
48
+ i(this, "localeControl", null);
49
+ i(this, "currencyControl", null);
50
+ i(this, "productCountControl", null);
51
+ i(this, "productLayoutControl", null);
52
+ i(this, "filtersControl", null);
53
+ i(this, "shuffleControl", null);
54
+ i(this, "pricePlacementControl", null);
55
+ i(this, "layoutOrientationControl", null);
56
+ i(this, "strategyControl", null);
57
+ i(this, "rrsEnabled", !1);
58
58
  /**
59
59
  * Debounced product fetch to prevent rapid API calls during config changes
60
60
  */
61
- r(this, "_debouncedFetchProducts", f(async () => {
61
+ i(this, "_debouncedFetchProducts", f(async () => {
62
62
  try {
63
63
  await this.store.fetchRecommendationProducts();
64
64
  } finally {
@@ -76,12 +76,12 @@ class at extends N {
76
76
  * count. The store pads products to the configured size, so in-place only
77
77
  * fails when the size actually changed.
78
78
  */
79
- r(this, "_debouncedRegenerateWithProducts", f(() => {
79
+ i(this, "_debouncedRegenerateWithProducts", f(() => {
80
80
  const t = this.store.recommendationProducts;
81
81
  if (!this.currentNode || !this.api)
82
82
  return;
83
83
  const e = this.api.getDocumentModifier(), o = this._stagePendingNodeConfig(e);
84
- if (v(this.currentNode)) {
84
+ if (B(this.currentNode)) {
85
85
  o && (e.apply(new y("Update recommendation configuration")), this.pendingNodeConfigWrite = null, this._clearConfigFlush());
86
86
  return;
87
87
  }
@@ -97,7 +97,7 @@ class at extends N {
97
97
  }, 100));
98
98
  }
99
99
  getId() {
100
- return $;
100
+ return W;
101
101
  }
102
102
  get _subControls() {
103
103
  return [
@@ -115,7 +115,7 @@ class at extends N {
115
115
  }
116
116
  getTemplate() {
117
117
  var t;
118
- return this.rrsEnabled = p().isFeatureEnabled("reusableRecommendationStrategy"), this._subControls.forEach((e) => {
118
+ return this.rrsEnabled = h().isFeatureEnabled("reusableRecommendationStrategy"), this._subControls.forEach((e) => {
119
119
  var o;
120
120
  return (o = e == null ? void 0 : e.onDestroy) == null ? void 0 : o.call(e);
121
121
  }), this.algorithmControl = new T(), this.localeControl = new L(), this.currencyControl = new P(), this.productCountControl = new E(), this.productLayoutControl = new F(), this.filtersControl = new S(), this.shuffleControl = new D(), this.pricePlacementControl = new k(), this.layoutOrientationControl = new O(), this.strategyControl = this.rrsEnabled ? new w() : null, this._subControls.forEach((e) => {
@@ -136,8 +136,8 @@ class at extends N {
136
136
  `;
137
137
  }
138
138
  _showControlsForBlock(t) {
139
- var i;
140
- const e = (i = this.getContainer()) == null ? void 0 : i.querySelector(".recommendation-controls-container");
139
+ var r;
140
+ const e = (r = this.getContainer()) == null ? void 0 : r.querySelector(".recommendation-controls-container");
141
141
  if (!e)
142
142
  return;
143
143
  const o = this._getRecommendationIdFromNode(t) === null ? null : c.getConfig(t), n = this.rrsEnabled && !!o && (!!(o != null && o.strategyId) || ((o == null ? void 0 : o.configVersion) ?? 0) >= _), s = this.rrsEnabled && !!o && !n;
@@ -147,7 +147,7 @@ class at extends N {
147
147
  var o;
148
148
  b(this.api);
149
149
  const t = this._getRecommendationIdFromNode(this.currentNode), e = t ?? this.store.currentRecommendationId;
150
- if (e !== null && this.store.setCurrentBlock(e), t !== null && this._syncNodeConfigIfChanged(t), this._listenStateUpdates(), this._showControlsForBlock(this.currentNode), e !== null && ((o = this.store.blockStates[e]) != null && o.isInitialized)) {
150
+ if (e !== null && this.store.setCurrentBlock(e), t !== null && this._syncNodeConfigIfChanged(t), this._listenStateUpdates(), this._showControlsForBlock(this.currentNode), t !== null && this.strategyControl && (this.strategyControl.api = this.api, this.strategyControl.currentNode = this.currentNode, this.strategyControl.onRender()), e !== null && ((o = this.store.blockStates[e]) != null && o.isInitialized)) {
151
151
  this._initializeSubControls();
152
152
  return;
153
153
  }
@@ -212,15 +212,27 @@ class at extends N {
212
212
  const o = JSON.stringify(c.getConfig(this.currentNode)), n = e.syncedConfigFingerprint;
213
213
  e.syncedConfigFingerprint = o, n !== o && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
214
214
  }
215
+ /** Whether the deferred write would move the node's strategyId — see the caller (SD-149916). */
216
+ _isPendingStrategyIdChange() {
217
+ const t = this.pendingNodeConfigWrite;
218
+ return t ? c.getConfig(this.currentNode).strategyId !== t.updates.strategyId : !1;
219
+ }
215
220
  _capturePendingNodeConfigWrite() {
216
221
  const t = this.store.currentRecommendationId;
217
222
  if (!this.currentNode || !this.api || t === null)
218
223
  return;
219
- const { filters: e, strategyId: o, size: n, nodeConfigVersion: s } = this.store.recommendationConfigs;
224
+ const { filters: e, strategy: o, strategyId: n, size: s, nodeConfigVersion: r } = this.store.recommendationConfigs, { partnerName: l } = h();
220
225
  this.pendingNodeConfigWrite = {
221
226
  blockId: t,
222
227
  node: this.currentNode,
223
- updates: { filters: e, strategyId: o, size: n, configVersion: s }
228
+ updates: {
229
+ filters: e,
230
+ strategy: o,
231
+ strategyId: n,
232
+ size: s,
233
+ configVersion: r,
234
+ ...l.value ? { partnerName: l.value } : {}
235
+ }
224
236
  };
225
237
  }
226
238
  /**
@@ -260,7 +272,7 @@ class at extends N {
260
272
  if (this.pendingNodeConfigWrite = null, this._clearConfigFlush(), !t || !this.api)
261
273
  return;
262
274
  const e = t.blockId === this.store.currentRecommendationId && this.currentNode ? this.currentNode : t.node, o = c.getConfig(e);
263
- JSON.stringify(o.filters) === JSON.stringify(t.updates.filters) && o.strategyId === t.updates.strategyId && o.size === t.updates.size || c.updateConfig(this.api, e, t.updates, "Update recommendation filters");
275
+ JSON.stringify(o.filters) === JSON.stringify(t.updates.filters) && o.strategy === t.updates.strategy && o.strategyId === t.updates.strategyId && o.size === t.updates.size || c.updateConfig(this.api, e, t.updates, "Update recommendation filters");
264
276
  }
265
277
  _syncNodeConfigToStore() {
266
278
  var n;
@@ -332,33 +344,33 @@ class at extends N {
332
344
  const t = c.getConfig(this.currentNode), e = {};
333
345
  let o = null, n = null, s = null;
334
346
  if (t.currency.code === a.currency.code) {
335
- const { currencyList: i } = this.store;
336
- i.length > 0 && (i.some(
347
+ const { currencyList: r } = this.store;
348
+ r.length > 0 && (r.some(
337
349
  (d) => d.value === `price.${a.currency.code}`
338
- ) || (o = i[0].value.replace("price.", ""), e.currency = {
350
+ ) || (o = r[0].value.replace("price.", ""), e.currency = {
339
351
  ...a.currency,
340
352
  code: o,
341
353
  symbol: o
342
354
  }));
343
355
  }
344
356
  if (t.strategy === a.strategy) {
345
- const i = this.store.getActivePredictiveAlgorithms;
346
- i.length > 0 && (i.some(
357
+ const r = this.store.getActivePredictiveAlgorithms;
358
+ r.length > 0 && (r.some(
347
359
  (d) => d.value === a.strategy
348
- ) || (n = i[0].value, e.strategy = n));
360
+ ) || (n = r[0].value, e.strategy = n));
349
361
  }
350
362
  if (t.language === a.language) {
351
- const i = this.store.getLanguages;
352
- i.length > 0 && (i.some(
363
+ const r = this.store.getLanguages;
364
+ r.length > 0 && (r.some(
353
365
  (d) => d.value === a.language
354
- ) || (s = i[0].value, e.language = s));
366
+ ) || (s = r[0].value, e.language = s));
355
367
  }
356
368
  !o && !n && !s || (c.updateConfig(
357
369
  this.api,
358
370
  this.currentNode,
359
371
  e,
360
372
  "Applied smart defaults"
361
- ), o && e.currency && A({
373
+ ), o && e.currency && v({
362
374
  currentNode: this.currentNode,
363
375
  documentModifier: this.api.getDocumentModifier(),
364
376
  currency: e.currency
@@ -382,7 +394,7 @@ class at extends N {
382
394
  * Reads the recommendation-id attribute from the block element within the node
383
395
  */
384
396
  _getRecommendationIdFromNode(t) {
385
- const e = B(t);
397
+ const e = A(t);
386
398
  if (!e || !("getAttribute" in e))
387
399
  return null;
388
400
  const o = e.getAttribute(I);
@@ -413,20 +425,20 @@ class at extends N {
413
425
  n = s, e = t.recommendationProducts, o = t.$state.configVersion;
414
426
  return;
415
427
  }
416
- const i = t.$state.configVersion;
417
- i !== o && (o = i, this._capturePendingNodeConfigWrite(), this._debouncedFetchProducts());
418
- const u = t.recommendationProducts, d = u !== e, h = Array.isArray(u) && u.length > 0;
419
- d && h && (e = u, this._debouncedRegenerateWithProducts());
428
+ const r = t.$state.configVersion;
429
+ r !== o && (o = r, this._capturePendingNodeConfigWrite(), this._isPendingStrategyIdChange() && this._flushPendingNodeConfig(), this._debouncedFetchProducts());
430
+ const l = t.recommendationProducts, d = l !== e, m = Array.isArray(l) && l.length > 0;
431
+ d && m && (e = l, this._debouncedRegenerateWithProducts());
420
432
  });
421
433
  }
422
434
  }
423
435
  export {
424
436
  ut as ALGORITHM_CONTROL_ID,
425
437
  T as AlgorithmControl,
426
- $ as CONTROL_BLOCK_ID,
438
+ W as CONTROL_BLOCK_ID,
427
439
  gt as CURRENCY_CONTROL_ID,
428
440
  P as CurrencyControl,
429
- ht as FILTERS_CONTROL_ID,
441
+ ft as FILTERS_CONTROL_ID,
430
442
  S as FiltersControl,
431
443
  Ct as LAYOUT_ORIENTATION_CONTROL_ID,
432
444
  yt as LOCALE_CONTROL_ID,
@@ -445,15 +457,15 @@ export {
445
457
  w as StrategyControl,
446
458
  Et as adjustProductsToSize,
447
459
  Ft as formatProductPrice,
448
- B as getBlockElement,
460
+ A as getBlockElement,
449
461
  Dt as getCardComposition,
450
462
  wt as getCurrentLayout,
451
- At as getMainContainerTbody,
452
- v as isPartnerManagedBlock,
453
- Bt as regenerateMobileProductRows,
463
+ vt as getMainContainerTbody,
464
+ B as isPartnerManagedBlock,
465
+ At as regenerateMobileProductRows,
454
466
  U as regenerateProductRowsWithStyles,
455
- A as setCurrencyAttributes,
456
- vt as updatePricesInPlace,
467
+ v as setCurrencyAttributes,
468
+ Bt as updatePricesInPlace,
457
469
  x as updateProductContentInPlace,
458
470
  xt as updateSingleProductContent
459
471
  };
@@ -1,49 +1,66 @@
1
- var p = Object.defineProperty;
2
- var v = (i, s, t) => s in i ? p(i, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[s] = t;
3
- var r = (i, s, t) => v(i, typeof s != "symbol" ? s + "" : s, t);
4
- import { useLegacyStrategyConversion as _ } from "../../../../../composables/useLegacyStrategyConversion.js";
5
- import { ACADEMY_LINKS as b } from "../../../../../enums/academy.js";
6
- import { useOnboardingStore as S } from "../../../../../stores/onboarding.js";
7
- import { CommonControl as f } from "../../../common-control.js";
8
- import { useRecommendationExtensionStore as $ } from "../../store/recommendation.js";
9
- const C = "recommendation-strategy-control";
10
- class N extends f {
1
+ var w = Object.defineProperty;
2
+ var N = (l, o, t) => o in l ? w(l, o, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[o] = t;
3
+ var i = (l, o, t) => N(l, typeof o != "symbol" ? o + "" : o, t);
4
+ import { useLegacyStrategyConversion as L } from "../../../../../composables/useLegacyStrategyConversion.js";
5
+ import { ACADEMY_LINKS as $ } from "../../../../../enums/academy.js";
6
+ import { useOnboardingStore as A } from "../../../../../stores/onboarding.js";
7
+ import { CommonControl as R } from "../../../common-control.js";
8
+ import { RRS_CONFIG_VERSION as E } from "../../constants/defaultConfig.js";
9
+ import { RecommendationConfigService as C } from "../../services/configService.js";
10
+ import { useRecommendationExtensionStore as O } from "../../store/recommendation.js";
11
+ const I = "recommendation-strategy-control";
12
+ class P extends R {
11
13
  constructor() {
12
14
  super(...arguments);
13
- r(this, "store", $());
14
- r(this, "onboardingStore", S());
15
- r(this, "legacyConversion", _());
16
- r(this, "storeUnsubscription", () => {
15
+ i(this, "store", O());
16
+ i(this, "onboardingStore", A());
17
+ i(this, "legacyConversion", L());
18
+ i(this, "storeUnsubscription", () => {
17
19
  });
18
- r(this, "listeners", []);
19
- r(this, "lastPaintedState", null);
20
+ i(this, "listeners", []);
21
+ i(this, "lastPaintedState", null);
20
22
  }
21
23
  getId() {
22
- return C;
24
+ return I;
23
25
  }
24
26
  getTemplate() {
25
27
  const t = this.api.translate(
26
28
  "You can assign a recommendation strategy by selecting an existing one or creating a new one to show specific content."
27
- ), e = this.api.translate("For more information, you can"), a = this.api.translate("visit Academy"), o = this.api.translate("Legacy Strategy"), n = this.api.translate(
29
+ ), e = this.api.translate("For more information, you can"), a = this.api.translate("visit Academy"), r = this.api.translate("Legacy Strategy"), s = this.api.translate(
28
30
  "Note that this is an older version of the Recommendation Strategy. We recommend you update it to the new Recommendation Strategy for an improved experience."
31
+ ), g = this.api.translate(
32
+ "The recommendation strategy used in the recommendation block is no longer available. You can assign a different strategy to it."
29
33
  );
30
34
  return `
31
35
  <div class="strategy-control-container">
32
- <div class="strategy-control-header">
33
- <h3 class="strategy-control-title">${this.api.translate("Recommendation Strategy")}</h3>
34
- </div>
35
- <div class="strategy-control-description-row">
36
- <p class="strategy-control-description">
37
- ${t}
38
- ${e}
39
- <a
40
- href="${b.EMAIL_RECOMMENDATION_BLOCK}"
41
- target="_blank"
42
- rel="noopener noreferrer">${a}</a>.
43
- </p>
36
+ <div data-strategy-loading-state>
37
+ <div class="strategy-control-header">
38
+ <span class="guido-skeleton guido-skeleton--strategy-title"></span>
39
+ </div>
40
+ <div class="strategy-control-description-row">
41
+ <span class="guido-skeleton guido-skeleton--strategy-description"></span>
42
+ </div>
43
+ <div class="strategy-control-skeleton-row">
44
+ <span class="guido-skeleton guido-skeleton--strategy-cta"></span>
45
+ <span class="guido-skeleton guido-skeleton--strategy-cta"></span>
46
+ </div>
44
47
  </div>
45
- <div data-strategy-empty-state>
46
- ${this._GuTwoColumns([
48
+ <div data-strategy-content style="display: none;">
49
+ <div class="strategy-control-header">
50
+ <h3 class="strategy-control-title">${this.api.translate("Recommendation Strategy")}</h3>
51
+ </div>
52
+ <div class="strategy-control-description-row">
53
+ <p class="strategy-control-description">
54
+ ${t}
55
+ ${e}
56
+ <a
57
+ href="${$.EMAIL_RECOMMENDATION_BLOCK}"
58
+ target="_blank"
59
+ rel="noopener noreferrer">${a}</a>.
60
+ </p>
61
+ </div>
62
+ <div data-strategy-empty-state style="display: none;">
63
+ ${this._GuTwoColumns([
47
64
  this._GuButton({
48
65
  name: "assignStrategy",
49
66
  label: this.api.translate("Assign Strategy"),
@@ -54,53 +71,76 @@ class N extends f {
54
71
  name: "createStrategy",
55
72
  label: this.api.translate("Create New Strategy"),
56
73
  id: "guido__btn-create-strategy",
57
- className: "strategy-control-cta primary",
58
- disabled: !0
74
+ className: "strategy-control-cta primary"
59
75
  })
60
76
  ], "strategy-control-cta-row")}
61
- </div>
62
- <div data-strategy-legacy-state style="display: none;">
63
- <div class="strategy-control-notice-row">
64
- <div class="strategy-control-notice">
65
- <p class="strategy-control-notice-text">${n}</p>
77
+ </div>
78
+ <div data-strategy-unavailable-state style="display: none;">
79
+ <div class="strategy-control-notice-row">
80
+ <div class="strategy-control-notice strategy-control-notice--error" role="alert">
81
+ <p class="strategy-control-notice-text">${g}</p>
82
+ </div>
66
83
  </div>
84
+ ${this._GuTwoColumns([
85
+ this._GuButton({
86
+ name: "assignUnavailableStrategy",
87
+ label: this.api.translate("Assign Strategy"),
88
+ id: "guido__btn-assign-unavailable-strategy",
89
+ className: "strategy-control-cta on"
90
+ }),
91
+ this._GuButton({
92
+ name: "createUnavailableStrategy",
93
+ label: this.api.translate("Create New Strategy"),
94
+ id: "guido__btn-create-unavailable-strategy",
95
+ className: "strategy-control-cta primary"
96
+ })
97
+ ], "strategy-control-cta-row")}
67
98
  </div>
68
- <div class="strategy-control-name-band">
69
- <span class="strategy-control-name">${o}</span>
70
- ${this._strategyAction({
99
+ <div data-strategy-legacy-state style="display: none;">
100
+ <div class="strategy-control-notice-row">
101
+ <div class="strategy-control-notice">
102
+ <p class="strategy-control-notice-text">${s}</p>
103
+ </div>
104
+ </div>
105
+ <div class="strategy-control-name-band">
106
+ <span class="strategy-control-name">${r}</span>
107
+ ${this._strategyAction({
71
108
  id: "guido__btn-update-legacy-strategy",
72
109
  label: this.api.translate("Update"),
73
110
  modifier: "update"
74
111
  })}
75
- </div>
76
- <div class="strategy-control-actions">
77
- ${this._strategyAction({
112
+ </div>
113
+ <div class="strategy-control-actions">
114
+ ${this._strategyAction({
78
115
  id: "guido__btn-change-legacy-strategy",
79
116
  label: this.api.translate("Change"),
80
117
  modifier: "change"
81
118
  })}
82
- ${this._strategyAction({
119
+ ${this._strategyAction({
83
120
  id: "guido__btn-remove-legacy-strategy",
84
121
  label: this.api.translate("Remove"),
85
122
  modifier: "remove"
86
123
  })}
124
+ </div>
87
125
  </div>
88
- </div>
89
- <div data-strategy-assigned-state style="display: none;">
90
- <div class="strategy-control-name-band">
91
- <span class="strategy-control-name" data-strategy-name></span>
92
- </div>
93
- <div class="strategy-control-actions">
94
- ${this._strategyAction({
126
+ <div data-strategy-assigned-state style="display: none;">
127
+ <div class="strategy-control-name-band">
128
+ <span class="strategy-control-name" data-strategy-name></span>
129
+ <span
130
+ class="guido-skeleton guido-skeleton--strategy-name" data-strategy-name-skeleton></span>
131
+ </div>
132
+ <div class="strategy-control-actions">
133
+ ${this._strategyAction({
95
134
  id: "guido__btn-change-strategy",
96
135
  label: this.api.translate("Change"),
97
136
  modifier: "change"
98
137
  })}
99
- ${this._strategyAction({
138
+ ${this._strategyAction({
100
139
  id: "guido__btn-remove-strategy",
101
140
  label: this.api.translate("Remove"),
102
141
  modifier: "remove"
103
142
  })}
143
+ </div>
104
144
  </div>
105
145
  </div>
106
146
  </div>
@@ -117,52 +157,66 @@ class N extends f {
117
157
  `;
118
158
  }
119
159
  onRender() {
120
- this._teardown(), this._setupButtonListeners(), this._renderState(), this.storeUnsubscription = this.store.$subscribe(() => {
160
+ this._teardown(), this.store.strategyPanelOpen = !0, this._setupButtonListeners(), this._renderState(), this.storeUnsubscription = this.store.$subscribe(() => {
121
161
  this._renderState();
122
- }), this.store.recommendationConfigs.strategyId && !this.store.strategies.length && this.store.fetchStrategies().catch(() => {
123
- });
124
- const t = this.store.currentRecommendationId, e = t !== null && !!this.store.blockStates[t], a = this.store.isLegacyStrategyBlock;
125
- e && !this.store.recommendationConfigs.strategyId && !a && this.onboardingStore.startOnboarding("recommendationStrategyOnboarding"), e && a && this.onboardingStore.startOnboarding("recommendationLegacyStrategyOnboarding");
162
+ }), this.store.recommendationConfigs.strategyId && !this.store.strategiesLoading && (this.store.invalidateStrategies(), this.store.fetchStrategies().catch(() => {
163
+ }));
164
+ }
165
+ /**
166
+ * Whether the document itself says this block has no strategy.
167
+ *
168
+ * Read the node, not the store: when the main control cannot resolve the block id off the
169
+ * node it never syncs the persisted config, so the store still holds defaults (empty
170
+ * strategyId) for an assigned block.
171
+ */
172
+ _isNodeUnassigned() {
173
+ if (!C.hasConfig(this.currentNode))
174
+ return !1;
175
+ const t = C.getConfig(this.currentNode);
176
+ return !t.strategyId && (t.configVersion ?? 0) >= E;
126
177
  }
127
178
  onDestroy() {
128
179
  this._teardown();
129
180
  }
130
181
  _teardown() {
131
- this.storeUnsubscription(), this.storeUnsubscription = () => {
182
+ this.store.strategyPanelOpen = !1, this.storeUnsubscription(), this.storeUnsubscription = () => {
132
183
  }, this.lastPaintedState = null, this.listeners.forEach(({ element: t, handler: e }) => t.removeEventListener("click", e)), this.listeners = [];
133
184
  }
134
185
  _setupButtonListeners() {
135
186
  const t = this.getContainer();
136
187
  if (!t)
137
188
  return;
138
- const e = (a, o) => {
139
- const n = t.querySelector(a);
140
- n && (n.addEventListener("click", o), this.listeners.push({ element: n, handler: o }));
189
+ const e = (a, r) => {
190
+ const s = t.querySelector(a);
191
+ s && (s.addEventListener("click", r), this.listeners.push({ element: s, handler: r }));
141
192
  };
142
- e("#guido__btn-assign-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-legacy-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-remove-strategy", () => this.store.openRemoveStrategyModal()), e("#guido__btn-remove-legacy-strategy", () => this.store.openRemoveStrategyModal()), e("#guido__btn-update-legacy-strategy", () => {
193
+ e("#guido__btn-assign-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-create-strategy", () => this.store.openStrategyCreation()), e("#guido__btn-assign-unavailable-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-create-unavailable-strategy", () => this.store.openStrategyCreation()), e("#guido__btn-change-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-legacy-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-remove-strategy", () => this.store.openRemoveStrategyModal()), e("#guido__btn-remove-legacy-strategy", () => this.store.openRemoveStrategyModal()), e("#guido__btn-update-legacy-strategy", () => {
143
194
  this.legacyConversion.convertLegacyStrategy();
144
195
  });
145
196
  }
146
197
  _renderState() {
147
- var h;
148
- const { strategyId: t } = this.store.recommendationConfigs, e = t ? ((h = this.store.assignedStrategy) == null ? void 0 : h.name) ?? "" : "", a = this.store.legacyConversionLoading, o = this.store.isLegacyStrategyBlock, n = `${t}\0${e}\0${a}\0${o}`;
149
- if (n === this.lastPaintedState)
198
+ var f;
199
+ const { strategyId: t } = this.store.recommendationConfigs, e = t ? ((f = this.store.assignedStrategy) == null ? void 0 : f.name) ?? "" : "", a = !!t && !e && (this.store.strategiesLoading || !this.store.strategiesSettled), r = !!t && !e && !a && this.store.strategiesFetched, s = this.store.legacyConversionLoading, g = this.store.isLegacyStrategyBlock, p = [t, e, a, r, s, g].join("\0");
200
+ if (p === this.lastPaintedState)
150
201
  return;
151
- const c = this.getContainer();
152
- if (!c)
202
+ const n = this.getContainer();
203
+ if (!n)
153
204
  return;
154
- const d = c.querySelector("[data-strategy-empty-state]"), y = c.querySelector("[data-strategy-assigned-state]"), g = c.querySelector("[data-strategy-legacy-state]"), m = c.querySelector("[data-strategy-name]");
155
- if (!d || !y || !g)
205
+ const y = n.querySelector("[data-strategy-empty-state]"), u = n.querySelector("[data-strategy-assigned-state]"), c = n.querySelector("[data-strategy-legacy-state]"), h = n.querySelector("[data-strategy-unavailable-state]"), v = n.querySelector("[data-strategy-loading-state]"), b = n.querySelector("[data-strategy-content]"), m = n.querySelector("[data-strategy-name]"), _ = n.querySelector("[data-strategy-name-skeleton]");
206
+ if (!y || !u || !c || !h)
156
207
  return;
157
- const u = t ? y : o ? g : d;
158
- [d, y, g].forEach((l) => {
159
- l.style.display = l === u ? "" : "none";
160
- }), g.querySelectorAll("button").forEach((l) => {
161
- l.disabled = a;
162
- }), g.classList.toggle("is-converting", a), m && t && (m.textContent = e || `#${t}`), this.lastPaintedState = n;
208
+ v && (v.style.display = "none"), b && (b.style.display = "");
209
+ const k = t ? r ? h : u : g ? c : y;
210
+ [y, u, c, h].forEach((d) => {
211
+ d.style.display = d === k ? "" : "none";
212
+ }), c.querySelectorAll("button").forEach((d) => {
213
+ d.disabled = s;
214
+ }), c.classList.toggle("is-converting", s), !t && this._isNodeUnassigned() && this.onboardingStore.startOnboarding("recommendationStrategyOnboarding");
215
+ const S = this.store.currentRecommendationId;
216
+ g && S !== null && this.store.blockStates[S] && this.onboardingStore.startOnboarding("recommendationLegacyStrategyOnboarding"), m && (m.style.display = a ? "none" : "", t && !a && (m.textContent = e || `#${t}`)), _ && (_.style.display = a ? "block" : "none"), this.lastPaintedState = p;
163
217
  }
164
218
  }
165
219
  export {
166
- C as STRATEGY_CONTROL_ID,
167
- N as StrategyControl
220
+ I as STRATEGY_CONTROL_ID,
221
+ P as StrategyControl
168
222
  };