@useinsider/guido 3.19.0 → 3.20.0-beta.7b31fec

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 (62) hide show
  1. package/README.md +21 -3
  2. package/dist/@types/config/schemas.js +59 -51
  3. package/dist/components/Guido.vue.js +4 -4
  4. package/dist/components/Guido.vue2.js +70 -68
  5. package/dist/components/organisms/base/Toaster.vue2.js +13 -12
  6. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +13 -11
  7. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +78 -57
  8. package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.js +18 -0
  9. package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue2.js +25 -0
  10. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +28 -42
  11. package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +28 -24
  12. package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.js +21 -0
  13. package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue2.js +46 -0
  14. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +21 -0
  15. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +47 -0
  16. package/dist/composables/useCustomInterfaceAppearance.js +65 -51
  17. package/dist/composables/useHtmlValidator.js +87 -82
  18. package/dist/composables/useLegacyStrategyConversion.js +61 -0
  19. package/dist/composables/useRecommendation.js +40 -35
  20. package/dist/composables/useStripo.js +30 -30
  21. package/dist/composables/useToaster.js +14 -20
  22. package/dist/enums/extensions/recommendationBlock.js +49 -33
  23. package/dist/extensions/Blocks/Recommendation/block.js +61 -42
  24. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +21 -20
  25. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +100 -94
  26. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +130 -55
  27. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +74 -74
  28. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +273 -92
  29. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js +42 -0
  30. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +26 -16
  31. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +24 -0
  32. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +21 -12
  33. package/dist/guido.css +1 -1
  34. package/dist/services/recommendationApi.js +46 -37
  35. package/dist/src/@types/config/schemas.d.ts +16 -0
  36. package/dist/src/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.d.ts +2 -0
  37. package/dist/src/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.d.ts +2 -0
  38. package/dist/src/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.d.ts +2 -0
  39. package/dist/src/composables/useConfig.d.ts +4 -0
  40. package/dist/src/composables/useLegacyStrategyConversion.d.ts +3 -0
  41. package/dist/src/enums/extensions/recommendationBlock.d.ts +7 -1
  42. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +10 -0
  43. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +1 -0
  44. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  45. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +2 -0
  46. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +10 -0
  47. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +7 -2
  48. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +162 -1
  49. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.d.ts +32 -0
  50. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +14 -0
  51. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +4 -0
  52. package/dist/src/services/recommendationApi.d.ts +2 -1
  53. package/dist/src/stores/config.d.ts +322 -0
  54. package/dist/src/stores/onboarding.d.ts +808 -10
  55. package/dist/static/assets/icons/filled-arrow-rising.svg.js +5 -0
  56. package/dist/static/assets/icons/line-info.svg.js +5 -0
  57. package/dist/static/styles/components/recommendation-strategy.css.js +104 -9
  58. package/dist/static/styles/components/skeleton.css.js +23 -0
  59. package/dist/stores/config.js +74 -60
  60. package/dist/stores/onboarding.js +46 -36
  61. package/dist/utils/templatePreparation.js +55 -55
  62. package/package.json +1 -1
@@ -1,22 +1,32 @@
1
- import { ModificationDescription as f } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- import { RECOMMENDATION_ID_ATTR as m } from "../constants/selectors.js";
3
- import { isPartnerManagedBlock as a, updateProductContentInPlace as d, regenerateProductRowsWithStyles as l } from "../controls/main/utils.js";
4
- import { RecommendationConfigService as s } from "../services/configService.js";
5
- let e = null;
6
- function N(r) {
7
- e = r;
1
+ import { ModificationDescription as g } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
+ import { RECOMMENDATION_ID_ATTR as s } from "../constants/selectors.js";
3
+ import { isPartnerManagedBlock as p, updateProductContentInPlace as C, regenerateProductRowsWithStyles as N } from "../controls/main/utils.js";
4
+ import { RecommendationConfigService as m } from "../services/configService.js";
5
+ let o = null;
6
+ function D(n) {
7
+ o = n;
8
8
  }
9
- function D(r, c, i, u) {
10
- const n = e == null ? void 0 : e.getDocumentRootHtmlNode();
11
- if (!e || !n || !("querySelector" in n))
9
+ function P(n, r, c, l) {
10
+ const i = o == null ? void 0 : o.getDocumentRootHtmlNode();
11
+ if (!o || !i || !("querySelector" in i))
12
12
  return !1;
13
- const t = n.querySelector(`[${m}="${r}"]`);
14
- if (!t)
13
+ const e = i.querySelector(`[${s}="${n}"]`);
14
+ if (!e)
15
15
  return !1;
16
- const o = e.getDocumentModifier();
17
- return s.stageConfig(o, t, c), a(t) ? (o.apply(new f(u)), !0) : (d({ currentNode: t, documentModifier: o, products: i }) || l({ currentNode: t, documentModifier: o, products: i }), !0);
16
+ const t = o.getDocumentModifier(), a = m.getConfig(e), d = Object.keys(r).some((u) => JSON.stringify(a[u]) !== JSON.stringify(r[u]));
17
+ if (m.stageConfig(t, e, r), p(e))
18
+ return t.apply(new g(l)), !0;
19
+ let f = !1;
20
+ return C({
21
+ currentNode: e,
22
+ documentModifier: t,
23
+ products: c,
24
+ onApplied: () => {
25
+ f = !0;
26
+ }
27
+ }) || (f = N({ currentNode: e, documentModifier: t, products: c })), !f && d && t.apply(new g(l)), !0;
18
28
  }
19
29
  export {
20
- D as commitBlockChangeOutsidePanel,
21
- N as registerNodeConfigWriter
30
+ P as commitBlockChangeOutsidePanel,
31
+ D as registerNodeConfigWriter
22
32
  };
@@ -0,0 +1,24 @@
1
+ import { useRecommendationExtensionStore as d } from "../store/recommendation.js";
2
+ import { commitBlockChangeOutsidePanel as f } from "./nodeConfigWriter.js";
3
+ async function h(e, r) {
4
+ const t = d(), o = t.blockStates[e];
5
+ if (!o)
6
+ return !1;
7
+ const { strategyId: a, strategy: c, size: i, nodeConfigVersion: s } = o.recommendationConfigs;
8
+ if (t.currentRecommendationId === e)
9
+ try {
10
+ await t.fetchRecommendationProducts();
11
+ } catch (m) {
12
+ console.error("[recommendation] product refetch after a strategy change failed", m);
13
+ }
14
+ const n = f(
15
+ e,
16
+ { strategyId: a, strategy: c, size: i, configVersion: s },
17
+ o.recommendationProducts,
18
+ r
19
+ );
20
+ return n || console.error("[recommendation] strategy change did not reach a node", { blockId: e }), n;
21
+ }
22
+ export {
23
+ h as commitStrategyChange
24
+ };
@@ -1,34 +1,43 @@
1
- const l = [
1
+ const o = "strategy", u = [
2
2
  {
3
3
  key: "locale",
4
4
  getValue: (e) => e.language,
5
5
  getAvailableOptions: (e) => Object.keys(e.languages)
6
6
  },
7
+ {
8
+ // A block feeds from either an assigned strategy (RRS) or an algorithm (legacy).
9
+ // Only a fresh RRS block has neither, and its feed URL would otherwise be built
10
+ // from an empty algorithm path.
11
+ key: o,
12
+ getValue: (e) => e.strategyId || e.strategy
13
+ },
7
14
  {
8
15
  key: "currency",
9
16
  getValue: (e) => e.currencySettings.value,
10
17
  getAvailableOptions: (e) => e.currencyList.map((n) => n.text),
11
18
  canBeEmpty: !0
12
19
  }
13
- ], o = "newsletter.recommendation-fill-required-fields";
14
- function c(e, n, i = l) {
20
+ ], l = "newsletter.recommendation-fill-required-fields", g = "newsletter.recommendation-assign-strategy";
21
+ function c(e, n, i = u) {
15
22
  return i.filter((t) => {
16
- var u;
23
+ var s;
17
24
  if (t.condition && !t.condition(e))
18
25
  return !1;
19
- const r = (u = t.getAvailableOptions) == null ? void 0 : u.call(t, n);
20
- if (t.canBeEmpty && (r == null ? void 0 : r.length) === 0)
26
+ const a = (s = t.getAvailableOptions) == null ? void 0 : s.call(t, n);
27
+ if (t.canBeEmpty && (a == null ? void 0 : a.length) === 0)
21
28
  return !1;
22
- const a = t.getValue(e);
23
- return a ? r !== void 0 && !r.includes(a) : !0;
29
+ const r = t.getValue(e);
30
+ return r ? a !== void 0 && !a.includes(r) : !0;
24
31
  }).map((t) => t.key);
25
32
  }
26
- function s(e, n) {
33
+ function y(e, n) {
27
34
  return c(e, n).length === 0;
28
35
  }
29
36
  export {
30
- l as REQUIRED_RECOMMENDATION_FIELDS,
31
- o as RecommendationRequiredFieldsKey,
37
+ u as REQUIRED_RECOMMENDATION_FIELDS,
38
+ g as RecommendationAssignStrategyKey,
39
+ l as RecommendationRequiredFieldsKey,
40
+ o as STRATEGY_FIELD_KEY,
32
41
  c as getInvalidFields,
33
- s as isConfigValid
42
+ y as isConfigValid
34
43
  };
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- @charset "UTF-8";.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-1ca6baf0]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-050dfa52]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-050dfa52]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-050dfa52]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-2580a7d9]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-2580a7d9] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}
1
+ @charset "UTF-8";.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-1ca6baf0]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-36867e2e]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-36867e2e]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-36867e2e]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-19d8cb42] .vueperslides__bullets,[data-v-ec2027ff] .vueperslides__bullets,[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-skeleton{width:100%!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}.legacy-strategy-updated-modal[data-v-da2225a1]{position:relative;z-index:145}
@@ -1,91 +1,100 @@
1
- import { useHttp as l } from "../composables/useHttp.js";
2
- import { URLS as m, QUERY_PARAMS as u } from "../enums/extensions/recommendationBlock.js";
3
- const y = "[sr_strategies.status][=][active]*[sr_strategies.suitable_channels][~][EMAIL]", R = (c) => c.reduce(
4
- (s, r, i) => (s[i] = {
5
- attributeName: r.attributeName,
6
- attributeJs: r.attributeJs,
7
- attributeType: r.attributeType,
8
- type: r.type,
9
- displayName: r.displayName,
10
- isFilterable: r.isFilterable
1
+ import { useHttp as y } from "../composables/useHttp.js";
2
+ import { MIGRATION_PATHS as R, URLS as i, QUERY_PARAMS as u } from "../enums/extensions/recommendationBlock.js";
3
+ const g = "[sr_strategies.status][=][active]*[sr_strategies.suitable_channels][~][EMAIL]", l = (r) => r.reduce(
4
+ (s, a, d) => (s[d] = {
5
+ attributeName: a.attributeName,
6
+ attributeJs: a.attributeJs,
7
+ attributeType: a.attributeType,
8
+ type: a.type,
9
+ displayName: a.displayName,
10
+ isFilterable: a.isFilterable
11
11
  }, s),
12
12
  {}
13
- ), _ = () => {
14
- const { get: c, post: s } = l(), { get: r } = l({ headers: {} }), i = "6KcLM9TwheVB1mgK";
13
+ ), h = (r) => r && typeof r == "object" && "data" in r ? r.data : r, w = () => {
14
+ const { get: r, post: s } = y(), { get: a } = y({ headers: {} }), d = "6KcLM9TwheVB1mgK";
15
15
  return {
16
16
  fetchRecommendationCreateData: async () => {
17
17
  try {
18
- return (await c("/newsletter/recommendations/create-data")).data;
18
+ return (await r(`${i.NEWSLETTER_RECOMMENDATIONS_PATH}/create-data`)).data;
19
19
  } catch (e) {
20
20
  throw console.error("fetchUserModalState error:", e), e;
21
21
  }
22
22
  },
23
23
  fetchRecommendationFilters: async () => {
24
24
  try {
25
- const { data: e } = await c(
26
- m.PRODUCT_ATTRIBUTES_PATH
27
- ), o = Array.isArray(e) ? e : (e == null ? void 0 : e.data) ?? [];
28
- return R(o);
25
+ const { data: e } = await r(
26
+ i.PRODUCT_ATTRIBUTES_PATH
27
+ ), n = Array.isArray(e) ? e : (e == null ? void 0 : e.data) ?? [];
28
+ return l(n);
29
29
  } catch (e) {
30
30
  throw console.error("fetchRecommendationFilters error:", e), e;
31
31
  }
32
32
  },
33
- fetchRecommendationProducts: async (e, o) => {
33
+ fetchRecommendationProducts: async (e, n) => {
34
34
  var t;
35
35
  try {
36
- const n = new URLSearchParams(Object.entries(o));
37
- n.set(u.CLIENT_ID, i);
38
- const d = decodeURIComponent(n.toString());
39
- console.debug("🏁 Recommendation API Query:", d);
40
- const a = await r(
41
- `${m.RECOMMENDATION_API_URL}/v2/${e}?${d}`
36
+ const o = new URLSearchParams(Object.entries(n));
37
+ o.set(u.CLIENT_ID, d);
38
+ const m = decodeURIComponent(o.toString());
39
+ console.debug("🏁 Recommendation API Query:", m);
40
+ const c = await a(
41
+ `${i.RECOMMENDATION_API_URL}/v2/${e}?${m}`
42
42
  );
43
- return ((t = a == null ? void 0 : a.data) == null ? void 0 : t.data) ?? [];
44
- } catch (n) {
45
- throw console.error("fetchRecommendationProducts error:", n), n;
43
+ return ((t = c == null ? void 0 : c.data) == null ? void 0 : t.data) ?? [];
44
+ } catch (o) {
45
+ throw console.error("fetchRecommendationProducts error:", o), o;
46
46
  }
47
47
  },
48
48
  fetchRecommendationProductsByUrl: async (e) => {
49
- var o;
49
+ var n;
50
50
  try {
51
- const t = new RegExp(`[?&]${u.CLIENT_ID}=`).test(e), n = e.includes("?") ? "&" : "?", d = t ? e : `${e}${n}${u.CLIENT_ID}=${i}`, a = await r(
52
- d
51
+ const t = new RegExp(`[?&]${u.CLIENT_ID}=`).test(e), o = e.includes("?") ? "&" : "?", m = t ? e : `${e}${o}${u.CLIENT_ID}=${d}`, c = await a(
52
+ m
53
53
  );
54
- return ((o = a == null ? void 0 : a.data) == null ? void 0 : o.data) ?? [];
54
+ return ((n = c == null ? void 0 : c.data) == null ? void 0 : n.data) ?? [];
55
55
  } catch (t) {
56
56
  return console.error("fetchRecommendationProductsByUrl error:", t), [];
57
57
  }
58
58
  },
59
59
  fetchRecommendationStrategies: async () => {
60
60
  try {
61
- const { data: e } = await c(
62
- `${m.RECOMMENDATION_STRATEGIES_PATH}?filters=${encodeURIComponent(y)}`
61
+ const { data: e } = await r(
62
+ `${i.RECOMMENDATION_STRATEGIES_PATH}?filters=${encodeURIComponent(g)}`
63
63
  );
64
64
  return Array.isArray(e) ? e : (e == null ? void 0 : e.data) ?? [];
65
65
  } catch (e) {
66
66
  throw console.error("fetchRecommendationStrategies error:", e), e;
67
67
  }
68
68
  },
69
- generateStrategyEndpoint: async (e, o) => {
69
+ generateStrategyEndpoint: async (e, n) => {
70
70
  try {
71
71
  const { data: t } = await s(
72
- `${m.RECOMMENDATION_STRATEGIES_PATH}/endpoint-generate`,
72
+ `${i.RECOMMENDATION_STRATEGIES_PATH}/endpoint-generate`,
73
73
  {
74
74
  campaignId: 0,
75
75
  pageTypes: [],
76
76
  isPreviewer: !1,
77
77
  strategy: e,
78
78
  userId: "",
79
- currency: o
79
+ currency: n
80
80
  }
81
81
  );
82
82
  return !t || typeof t != "object" || !("full_path" in t || "data" in t) ? (console.error("generateStrategyEndpoint unexpected response shape:", t), null) : "full_path" in t ? t : t.data;
83
83
  } catch (t) {
84
84
  return console.error("generateStrategyEndpoint error:", t), null;
85
85
  }
86
+ },
87
+ migrateLegacyStrategy: async (e, n = { scope: "campaign" }) => {
88
+ const { data: t } = await s(
89
+ R[n.scope],
90
+ e
91
+ ), { strategyId: o } = h(t) ?? {};
92
+ if (o == null || o === "")
93
+ throw new Error("[Guido] migrate-strategies returned no strategyId");
94
+ return String(o);
86
95
  }
87
96
  };
88
97
  };
89
98
  export {
90
- _ as useRecommendationApi
99
+ w as useRecommendationApi
91
100
  };
@@ -50,6 +50,14 @@ export declare const IdentitySchema: v.ObjectSchema<{
50
50
  readonly userId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, "userId is required">]>;
51
51
  /** Optional variation ID for A/B testing */
52
52
  readonly variationId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
53
+ /** Optional numeric campaign ID of the host campaign; absent for templates and modules */
54
+ readonly campaignId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
55
+ /**
56
+ * Optional numeric template-library id of the host template; absent for campaigns and
57
+ * modules. Distinct from `templateId`, which is the editor's document identity (a uuid /
58
+ * Stripo doc id) and is never an endpoint id.
59
+ */
60
+ readonly templateLibraryId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
53
61
  }, undefined>;
54
62
  /**
55
63
  * Partner configuration - organization and product context
@@ -625,6 +633,14 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
625
633
  readonly userId: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, "userId is required">]>;
626
634
  /** Optional variation ID for A/B testing */
627
635
  readonly variationId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
636
+ /** Optional numeric campaign ID of the host campaign; absent for templates and modules */
637
+ readonly campaignId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
638
+ /**
639
+ * Optional numeric template-library id of the host template; absent for campaigns and
640
+ * modules. Distinct from `templateId`, which is the editor's document identity (a uuid /
641
+ * Stripo doc id) and is never an endpoint id.
642
+ */
643
+ readonly templateLibraryId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
628
644
  }, undefined>;
629
645
  /** Partner configuration (required) */
630
646
  readonly partner: v.ObjectSchema<{
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
2
+ export default _default;
@@ -11,6 +11,8 @@ export declare const useConfig: () => {
11
11
  templateId: string;
12
12
  userId: string;
13
13
  variationId?: string | undefined;
14
+ campaignId?: string | undefined;
15
+ templateLibraryId?: string | undefined;
14
16
  };
15
17
  partner: {
16
18
  name: string;
@@ -146,6 +148,8 @@ export declare const useConfig: () => {
146
148
  templateId: string;
147
149
  userId: string;
148
150
  variationId?: string | undefined;
151
+ campaignId?: string | undefined;
152
+ templateLibraryId?: string | undefined;
149
153
  } | null>;
150
154
  partner: import("vue").ComputedRef<{
151
155
  name: string;
@@ -0,0 +1,3 @@
1
+ export declare const useLegacyStrategyConversion: () => {
2
+ convertLegacyStrategy: () => Promise<string>;
3
+ };
@@ -1,11 +1,17 @@
1
1
  import type { TextValueObject } from '@@/Types/generic';
2
- import type { RecommendationFeedItem } from '@@/Types/recommendation';
2
+ import type { RecommendationFeedItem, RrsMigrationTarget } from '@@/Types/recommendation';
3
3
  export declare const URLS: {
4
4
  RECOMMENDATION_API_URL: string;
5
5
  PRODUCT_ATTRIBUTES_PATH: string;
6
6
  RECOMMENDATION_STRATEGIES_PATH: string;
7
7
  RECOMMENDATION_STRATEGIES_PANEL_PATH: string;
8
+ NEWSLETTER_RECOMMENDATIONS_PATH: string;
9
+ MIGRATE_STRATEGIES_PATH: string;
10
+ TEMPLATE_MIGRATE_STRATEGIES_PATH: string;
11
+ RECOMMENDATION_STRATEGY_CREATE_PATH: string;
8
12
  };
13
+ export declare const strategyEditPath: (strategyId: string | number) => string;
14
+ export declare const MIGRATION_PATHS: Record<RrsMigrationTarget['scope'], string>;
9
15
  export declare const QUERY_PARAMS: {
10
16
  CLIENT_ID: string;
11
17
  };
@@ -15,6 +15,8 @@ export declare class RecommendationBlock extends Block {
15
15
  * This avoids generating a new (different) ID in onCreated().
16
16
  */
17
17
  private _pendingBlockId;
18
+ /** Ids already reset under their new name, so the deferred pass skips their stale snapshot. */
19
+ private _resetSourceIds;
18
20
  constructor();
19
21
  getId(): string;
20
22
  getIcon(): string;
@@ -73,6 +75,14 @@ export declare class RecommendationBlock extends Block {
73
75
  * in the document and finding the maximum existing ID + 1.
74
76
  */
75
77
  private _generateNextId;
78
+ /**
79
+ * Drops the "already fetched" claims of a block that arrived holding a baked id
80
+ * (saved module, paste, duplicate), so the settings panel reads its strategy again.
81
+ *
82
+ * Deferred a tick: the collision handlers rename a sibling first, and either sibling can be
83
+ * the renamed one depending on where the module was dropped (SD-149916).
84
+ */
85
+ private _scheduleArrivalReset;
76
86
  /**
77
87
  * Heals a duplicate that slipped past the create-time `_detectDuplicate`
78
88
  * scan (or that was persisted by an older template before SD-142352).
@@ -10,6 +10,7 @@
10
10
  import type { RecommendationNodeConfig, CurrencyConfig, OmnibusTextConfig } from '../types/nodeConfig';
11
11
  export declare const PRE_RRS_CONFIG_VERSION = 1;
12
12
  export declare const CURRENT_CONFIG_VERSION = 2;
13
+ export declare const RRS_CONFIG_VERSION = 2;
13
14
  /**
14
15
  * Default currency configuration
15
16
  * Uses USD as the base currency with standard formatting
@@ -10,4 +10,4 @@ export { RecommendationBlockId } from './blockIds';
10
10
  export { RecommendationControlId } from './controlIds';
11
11
  export { BLOCK_ROOT_SELECTOR, CONTAINER_SELECTOR, DESKTOP_CONTAINER_SELECTOR, MOBILE_CONTAINER_SELECTOR, MOBILE_ROW_SELECTOR, CSS_CLASS_RECO_BUTTON, CSS_CLASS_SKIP_COMPILE, RECOMMENDATION_VARIABLE_BUILTIN_ATTRIBUTES, CURRENCY_ATTR, ATTR_PRODUCT_IMAGE, ATTR_PRODUCT_NAME, ATTR_PRODUCT_PRICE, ATTR_PRODUCT_OLD_PRICE, ATTR_PRODUCT_OMNIBUS_PRICE, ATTR_PRODUCT_OMNIBUS_DISCOUNT, ATTR_PRODUCT_BUTTON, ATTR_RECOMMENDATION_TITLE, SELECTOR_TITLE_CELL, ATTR_CUSTOM_PREFIX, ATTR_DATA_CARD_COMPOSITION, ATTR_DATA_CUSTOM_ATTRIBUTES, ATTR_PRODUCT_ATTR, CSS_CLASS_ATTRIBUTE_ROW, CSS_CLASS_SPACER, SELECTOR_ATTRIBUTE_ROW, ATTR_DATA_ATTRIBUTE_TYPE, ATTR_DATA_VISIBILITY, PRODUCT_ATTRIBUTE_PREFIX, BUILT_IN_DEFAULT_ATTRIBUTES, } from './selectors';
12
12
  export { LAYOUT_VALUES, LAYOUT_OPTIONS, DEFAULT_PRODUCTS_PER_ROW, DEFAULT_CARDS_IN_ROW, DEFAULT_MOBILE_CARDS_IN_ROW, MAX_PRODUCT_COUNT, MIN_PRODUCT_COUNT, MAX_PRODUCTS_PER_ROW, MIN_PRODUCTS_PER_ROW, MAX_MOBILE_PRODUCTS_PER_ROW, MIN_MOBILE_PRODUCTS_PER_ROW, DEFAULT_COLUMN_SPACING, DEFAULT_ROW_SPACING, DEFAULT_MOBILE_COLUMN_SPACING, DEFAULT_MOBILE_ROW_SPACING, MIN_SPACING, MAX_SPACING, SPACING_STEP, } from './layout';
13
- export { DEFAULT_NODE_CONFIG, DEFAULT_CURRENCY, DEFAULT_COMPOSITION, DEFAULT_VISIBILITY, CURRENT_CONFIG_VERSION, PRE_RRS_CONFIG_VERSION, EXCLUDED_ALGORITHM_IDS, } from './defaultConfig';
13
+ export { DEFAULT_NODE_CONFIG, DEFAULT_CURRENCY, DEFAULT_COMPOSITION, DEFAULT_VISIBILITY, CURRENT_CONFIG_VERSION, PRE_RRS_CONFIG_VERSION, RRS_CONFIG_VERSION, EXCLUDED_ALGORITHM_IDS, } from './defaultConfig';
@@ -70,6 +70,8 @@ export declare class RecommendationBlockControl extends CommonControl {
70
70
  * state was rebuilt with (SD-150347).
71
71
  */
72
72
  private _syncNodeConfigIfChanged;
73
+ /** Whether the deferred write would move the node's strategyId — see the caller (SD-149916). */
74
+ private _isPendingStrategyIdChange;
73
75
  private _capturePendingNodeConfigWrite;
74
76
  /**
75
77
  * Accumulates the pending write into `documentModifier` without applying, so the
@@ -2,6 +2,8 @@ import { CommonControl } from '../../../common-control';
2
2
  export declare const STRATEGY_CONTROL_ID = "recommendation-strategy-control";
3
3
  export declare class StrategyControl extends CommonControl {
4
4
  private store;
5
+ private onboardingStore;
6
+ private legacyConversion;
5
7
  private storeUnsubscription;
6
8
  private listeners;
7
9
  private lastPaintedState;
@@ -9,6 +11,14 @@ export declare class StrategyControl extends CommonControl {
9
11
  getTemplate(): string;
10
12
  private _strategyAction;
11
13
  onRender(): void;
14
+ /**
15
+ * Whether the document itself says this block has no strategy.
16
+ *
17
+ * Read the node, not the store: when the main control cannot resolve the block id off the
18
+ * node it never syncs the persisted config, so the store still holds defaults (empty
19
+ * strategyId) for an assigned block.
20
+ */
21
+ private _isNodeUnassigned;
12
22
  onDestroy(): void;
13
23
  private _teardown;
14
24
  private _setupButtonListeners;
@@ -107,7 +107,7 @@ export interface RegenerateWithStylesOptions extends Omit<RegenerateProductRowsO
107
107
  * HTML removes the need for any post-rebuild reapply pass.
108
108
  * @param options - Configuration options for regeneration
109
109
  */
110
- export declare function regenerateProductRowsWithStyles(options: RegenerateWithStylesOptions): void;
110
+ export declare function regenerateProductRowsWithStyles(options: RegenerateWithStylesOptions): boolean;
111
111
  /**
112
112
  * Adjusts a products array to a target size.
113
113
  * Used by ProductLayoutControl to synchronously match products to the new size
@@ -151,6 +151,11 @@ export interface UpdateProductContentInPlaceOptions {
151
151
  currentNode: ImmutableHtmlNode | null | undefined;
152
152
  documentModifier: DocumentModifier;
153
153
  products: RecommendationProduct[];
154
+ /**
155
+ * Called when the batch was actually committed. Identical products commit nothing, which
156
+ * leaves anything a caller staged into the same batch unwritten unless it applies itself.
157
+ */
158
+ onApplied?: () => void;
154
159
  }
155
160
  /**
156
161
  * Updates product content in-place without regenerating HTML structure.
@@ -161,7 +166,7 @@ export interface UpdateProductContentInPlaceOptions {
161
166
  * After updating desktop, also updates mobile container to keep them in sync.
162
167
  *
163
168
  * Falls back to false when product count changed (need to add/remove elements).
164
- * @param options - Configuration options
169
+ * @param options - Configuration options; `onApplied` fires only when a batch was committed
165
170
  * @returns true if in-place update was successful, false to fall back to full regeneration
166
171
  */
167
172
  export declare function updateProductContentInPlace(options: UpdateProductContentInPlaceOptions): boolean;