@useinsider/guido 3.18.1-beta.fefef3c → 3.18.2-beta.32d291d

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.
@@ -1,64 +1,64 @@
1
- import { defineComponent as A, ref as c, computed as b, toRef as h, nextTick as C } from "vue";
2
- import N from "../../wrappers/WpDrawer.vue.js";
3
- import { useTranslations as O } from "../../../composables/useTranslations.js";
1
+ import { defineComponent as _, ref as c, computed as h, watch as C, toRef as N, nextTick as O } from "vue";
2
+ import b from "../../wrappers/WpDrawer.vue.js";
3
+ import { useTranslations as D } from "../../../composables/useTranslations.js";
4
4
  import { useTemplateNameValidator as x } from "../../../composables/validators/saveAsTemplate.js";
5
5
  import { useTemplateLibraryApi as B } from "../../../services/templateLibraryApi.js";
6
- import { useEditorStore as D } from "../../../stores/editor.js";
7
- import { useSaveAsTemplateStore as k } from "../../../stores/save-as-template.js";
8
- import { InMultiSelect as I, InBasicTextInput as M } from "@useinsider/design-system-vue";
9
- import { useDebounceFn as V } from "../../../node_modules/@vueuse/shared/index.js";
10
- const H = /* @__PURE__ */ A({
6
+ import { useEditorStore as k } from "../../../stores/editor.js";
7
+ import { useSaveAsTemplateStore as I } from "../../../stores/save-as-template.js";
8
+ import { InMultiSelect as M, InBasicTextInput as V } from "@useinsider/design-system-vue";
9
+ import { useDebounceFn as E } from "../../../node_modules/@vueuse/shared/index.js";
10
+ const J = /* @__PURE__ */ _({
11
11
  __name: "SaveAsTemplateDrawer",
12
- setup(E) {
13
- const o = O(), n = D(), t = k(), { createTemplate: m } = B(), a = c(!1), r = c(!1), l = c(""), f = b(() => ({
12
+ setup(R) {
13
+ const s = D(), o = k(), t = I(), { createTemplate: m } = B(), a = c(!1), n = c(!1), r = c(""), f = h(() => ({
14
14
  primaryButton: {
15
15
  styling: "solid",
16
16
  type: "primary",
17
- labelText: o(a.value ? "newsletter.saving" : "products.save"),
17
+ labelText: s(a.value ? "newsletter.saving" : "products.save"),
18
18
  loadingStatus: a.value,
19
19
  disabledStatus: t.skeletonStatus
20
20
  },
21
21
  cancelOrBackButton: {
22
22
  styling: "ghost",
23
23
  type: "secondary",
24
- labelText: o("products.cancel"),
24
+ labelText: s("products.cancel"),
25
25
  disabledStatus: a.value
26
26
  }
27
- })), u = () => {
28
- l.value = "", n.isSaveAsTemplateDrawerOpen = !1;
29
- }, i = async () => {
30
- const e = h(t, "templateName"), { success: s, errorMessage: _ } = await x(e).validate();
31
- return l.value = _, s;
32
- }, v = V(async (e) => {
33
- t.templateName = e, await i();
34
- }, 500), g = async (e) => {
35
- r.value = !0, await t.addCategory(e), r.value = !1;
36
- }, y = (e) => {
27
+ })), p = () => {
28
+ r.value = "", o.isSaveAsTemplateDrawerOpen = !1;
29
+ }, l = async () => {
30
+ const e = N(t, "templateName"), { success: i, errorMessage: A } = await x(e).validate();
31
+ return r.value = A, i;
32
+ }, v = E(async (e) => {
33
+ t.templateName = e, await l();
34
+ }, 500), S = async (e) => {
35
+ n.value = !0, await t.addCategory(e), n.value = !1;
36
+ }, T = (e) => {
37
37
  t.selectedCategories = e;
38
- }, S = (e) => {
38
+ }, g = (e) => {
39
39
  e && (t.selectedCategories = e);
40
- }, T = () => {
40
+ }, y = () => {
41
41
  t.selectedCategories = [];
42
42
  }, w = async () => {
43
- if (a.value = !0, !await i()) {
43
+ if (a.value = !0, !await l()) {
44
44
  a.value = !1;
45
45
  return;
46
46
  }
47
- const s = await m();
48
- a.value = !1, s && u();
49
- }, p = () => {
50
- C(() => {
47
+ const i = await m();
48
+ a.value = !1, i && p();
49
+ }, u = () => {
50
+ O(() => {
51
51
  const e = document.querySelector("input#guido__template-name-input");
52
52
  e == null || e.focus();
53
53
  });
54
54
  }, d = async () => {
55
- t.$reset(), await t.fetchCategories(), t.skeletonStatus = !1, p();
55
+ t.$reset(), await t.fetchCategories(), t.skeletonStatus = !1, u();
56
56
  };
57
- return n.$subscribe((e, { isSaveAsTemplateDrawerOpen: s }) => {
58
- s && d();
59
- }), { __sfc: !0, trans: o, editorStore: n, saveAsTemplateStore: t, createTemplate: m, isSaving: a, isAddingOption: r, templateNameError: l, footerButtonGroupOptions: f, closeModal: u, validateTemplateName: i, handleTemplateName: v, handleAddOption: g, handleCategoryChange: y, handleSelectAllOptions: S, handleResetAllOptions: T, saveTemplate: w, focusToInput: p, initializeDrawer: d, WpDrawer: N, InBasicTextInput: M, InMultiSelect: I };
57
+ return C(() => o.isSaveAsTemplateDrawerOpen, (e) => {
58
+ e && d();
59
+ }), { __sfc: !0, trans: s, editorStore: o, saveAsTemplateStore: t, createTemplate: m, isSaving: a, isAddingOption: n, templateNameError: r, footerButtonGroupOptions: f, closeModal: p, validateTemplateName: l, handleTemplateName: v, handleAddOption: S, handleCategoryChange: T, handleSelectAllOptions: g, handleResetAllOptions: y, saveTemplate: w, focusToInput: u, initializeDrawer: d, WpDrawer: b, InBasicTextInput: V, InMultiSelect: M };
60
60
  }
61
61
  });
62
62
  export {
63
- H as default
63
+ J as default
64
64
  };
@@ -1,14 +1,16 @@
1
- import { getCsrfToken as H } from "../utils/genericUtil.js";
2
- import { ref as p, computed as T } from "vue";
3
- const k = (b = {}) => {
4
- const h = p(!1), a = p(null), u = p(null), g = T(() => h.value), y = T(() => a.value !== null), v = {
1
+ import { getCsrfToken as O } from "../utils/genericUtil.js";
2
+ import { ref as m, computed as T } from "vue";
3
+ const X = (b = {}) => {
4
+ const p = m(!1), a = m(null), u = m(null), g = T(() => p.value), y = T(() => a.value !== null), v = {
5
5
  baseURL: "",
6
6
  timeout: 1e4,
7
7
  retry: 0,
8
8
  retryDelay: 1e3,
9
9
  headers: {
10
10
  "Content-Type": "application/json",
11
- "X-CSRF-TOKEN": H()
11
+ "X-CSRF-TOKEN": O(),
12
+ Accept: "application/json",
13
+ "X-Requested-With": "XMLHttpRequest"
12
14
  },
13
15
  ...b
14
16
  }, w = (e, s) => {
@@ -22,22 +24,22 @@ const k = (b = {}) => {
22
24
  }, e);
23
25
  }), x = (e) => new Promise((s) => {
24
26
  setTimeout(s, e);
25
- }), i = async (e, s, t, D = {}) => {
26
- a.value = null, h.value = !0, u.value = new AbortController();
27
- const n = { ...v, ...D }, L = w(s, n.baseURL), c = {
27
+ }), i = async (e, s, t, L = {}) => {
28
+ a.value = null, p.value = !0, u.value = new AbortController();
29
+ const n = { ...v, ...L }, D = w(s, n.baseURL), c = {
28
30
  method: e,
29
31
  headers: { ...n.headers },
30
32
  signal: u.value.signal,
31
33
  ...n
32
34
  };
33
35
  t && ["POST", "PUT", "PATCH"].includes(e) && (t instanceof FormData ? (delete c.headers["Content-Type"], c.body = t) : c.body = JSON.stringify(t));
34
- const E = async (m = 0) => {
36
+ const E = async (h = 0) => {
35
37
  try {
36
- const o = [fetch(L, c)];
38
+ const o = [fetch(D, c)];
37
39
  n.timeout && o.push(P(n.timeout));
38
40
  const r = await Promise.race(o);
39
41
  if (!r.ok) {
40
- const O = `HTTP Error: ${r.status} ${r.statusText}`, d = new Error(O);
42
+ const H = `HTTP Error: ${r.status} ${r.statusText}`, d = new Error(H);
41
43
  throw d.status = r.status, d.statusText = r.statusText, d.response = r, d;
42
44
  }
43
45
  let f;
@@ -50,19 +52,19 @@ const k = (b = {}) => {
50
52
  };
51
53
  } catch (o) {
52
54
  const r = o instanceof Error && o.name === "AbortError";
53
- if (m < (n.retry || 0) && !r)
54
- return await x(n.retryDelay || 1e3), E(m + 1);
55
+ if (h < (n.retry || 0) && !r)
56
+ return await x(n.retryDelay || 1e3), E(h + 1);
55
57
  throw o instanceof Error ? o.name === "AbortError" ? a.value = { message: "Request was cancelled" } : a.value = { message: o.message } : a.value = o, o;
56
58
  }
57
59
  };
58
60
  try {
59
61
  return await E();
60
62
  } finally {
61
- h.value = !1, u.value = null;
63
+ p.value = !1, u.value = null;
62
64
  }
63
- }, C = (e, s) => i("GET", e, void 0, s), $ = (e, s, t) => i("POST", e, s, t), R = (e, s, t) => i("PUT", e, s, t), U = (e, s, t) => i("PATCH", e, s, t), A = (e, s) => i("DELETE", e, void 0, s), W = (e) => {
65
+ }, C = (e, s) => i("GET", e, void 0, s), R = (e, s, t) => i("POST", e, s, t), $ = (e, s, t) => i("PUT", e, s, t), q = (e, s, t) => i("PATCH", e, s, t), A = (e, s) => i("DELETE", e, void 0, s), U = (e) => {
64
66
  u.value && u.value.abort(e);
65
- }, q = () => {
67
+ }, W = () => {
66
68
  a.value = null;
67
69
  };
68
70
  return {
@@ -73,14 +75,14 @@ const k = (b = {}) => {
73
75
  // Methods
74
76
  request: i,
75
77
  get: C,
76
- post: $,
77
- put: R,
78
- patch: U,
78
+ post: R,
79
+ put: $,
80
+ patch: q,
79
81
  delete: A,
80
- cancel: W,
81
- clearError: q
82
+ cancel: U,
83
+ clearError: W
82
84
  };
83
85
  };
84
86
  export {
85
- k as useHttp
87
+ X as useHttp
86
88
  };
@@ -1,61 +1,61 @@
1
- import { useRecommendation as f } from "./useRecommendation.js";
2
- import { useToaster as S } from "./useToaster.js";
3
- import { useTranslations as I } from "./useTranslations.js";
4
- import { ToasterTypeOptions as C } from "../enums/toaster.js";
1
+ import { useRecommendation as I } from "./useRecommendation.js";
2
+ import { useToaster as C } from "./useToaster.js";
3
+ import { useTranslations as v } from "./useTranslations.js";
4
+ import { ToasterTypeOptions as g } from "../enums/toaster.js";
5
5
  import "../extensions/Blocks/Recommendation/constants/selectors.js";
6
6
  import { CURRENT_CONFIG_VERSION as L } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
7
- import { useRecommendationExtensionStore as v } from "../extensions/Blocks/Recommendation/store/recommendation.js";
8
- import { resolveMigrationTarget as b, buildLegacyMigrationPayload as R } from "../extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js";
9
- import { commitBlockChangeOutsidePanel as T } from "../extensions/Blocks/Recommendation/utils/nodeConfigWriter.js";
10
- import { useConfigStore as h } from "../stores/config.js";
11
- const V = () => {
12
- const t = v(), o = h(), { buildCampaignUrl: s } = f(), { showToaster: m } = S(), g = I();
7
+ import { useRecommendationExtensionStore as b } from "../extensions/Blocks/Recommendation/store/recommendation.js";
8
+ import { resolveMigrationTarget as R, buildLegacyMigrationPayload as T } from "../extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js";
9
+ import { commitBlockChangeOutsidePanel as h } from "../extensions/Blocks/Recommendation/utils/nodeConfigWriter.js";
10
+ import { useConfigStore as k } from "../stores/config.js";
11
+ const F = () => {
12
+ const e = b(), r = k(), { buildCampaignUrl: m } = I(), { showToaster: i } = C(), c = v();
13
13
  return { convertLegacyStrategy: async () => {
14
- const e = t.currentRecommendationId;
15
- if (e === null || !t.isLegacyStrategyBlock || t.legacyConversionLoading)
14
+ const t = e.currentRecommendationId;
15
+ if (t === null || !e.isLegacyStrategyBlock || e.legacyConversionLoading)
16
16
  return "";
17
- const { strategy: d, productIds: l, filters: y } = t.recommendationConfigs, i = b({
18
- campaignId: o.campaignId,
19
- templateLibraryId: o.templateLibraryId
20
- }), p = R({
21
- blockId: e,
22
- url: s(String(e)),
23
- campaignId: o.campaignId,
24
- variationId: o.variationId,
17
+ const { strategy: d, productIds: y, size: l, strategyId: p, nodeConfigVersion: u } = e.recommendationConfigs, f = { strategyId: p, size: l, nodeConfigVersion: u }, s = R({
18
+ campaignId: r.campaignId,
19
+ templateLibraryId: r.templateLibraryId
20
+ }), S = T({
21
+ blockId: t,
22
+ url: m(String(t)),
23
+ campaignId: r.campaignId,
24
+ variationId: r.variationId,
25
25
  strategy: d,
26
- productIds: l,
27
- filters: y,
28
- attributes: t.getFilterList,
29
- target: i
26
+ productIds: y,
27
+ target: s
30
28
  });
31
- let r;
29
+ let o;
32
30
  try {
33
- r = await t.convertLegacyStrategy(p, i);
31
+ o = await e.convertLegacyStrategy(S, s);
34
32
  } catch (n) {
35
- return console.error("[useLegacyStrategyConversion] migration failed", n), m({
36
- type: C.Error,
37
- message: g("email-editor.legacy-strategy-update-failed")
33
+ return console.error("[useLegacyStrategyConversion] migration failed", n), i({
34
+ type: g.Error,
35
+ message: c("email-editor.legacy-strategy-update-failed")
38
36
  }), "";
39
37
  }
40
- const c = t.currentRecommendationId === e;
41
- if (c)
42
- try {
43
- await t.fetchRecommendationProducts();
44
- } catch (n) {
45
- console.error("[useLegacyStrategyConversion] product refetch failed", n);
46
- }
47
- const a = t.blockStates[e];
48
- if (!a)
49
- return r;
50
- const { size: u } = a.recommendationConfigs;
51
- return T(
52
- e,
53
- { strategyId: r, size: u, configVersion: L },
38
+ try {
39
+ await e.fetchStrategyProductsForBlock(t);
40
+ } catch (n) {
41
+ console.error("[useLegacyStrategyConversion] product refetch failed", n);
42
+ }
43
+ const a = e.blockStates[t];
44
+ return a ? h(
45
+ t,
46
+ {
47
+ strategyId: o,
48
+ size: a.recommendationConfigs.size,
49
+ configVersion: L
50
+ },
54
51
  a.recommendationProducts,
55
52
  "Converted legacy recommendation strategy"
56
- ), c && t.openLegacyStrategyUpdatedModal(), r;
53
+ ) ? (e.currentRecommendationId === t && e.openLegacyStrategyUpdatedModal(), o) : (console.error("[useLegacyStrategyConversion] node write failed", t), e.revertLegacyConversion(t, f), i({
54
+ type: g.Error,
55
+ message: c("email-editor.legacy-strategy-update-failed")
56
+ }), "") : o;
57
57
  } };
58
58
  };
59
59
  export {
60
- V as useLegacyStrategyConversion
60
+ F as useLegacyStrategyConversion
61
61
  };
@@ -1,15 +1,22 @@
1
- import { useTranslations as r } from "../../composables/useTranslations.js";
2
- const l = {
1
+ import { useTranslations as n } from "../../composables/useTranslations.js";
2
+ const a = {
3
3
  RECOMMENDATION_API_URL: "https://recommendationv2.api.useinsider.com",
4
4
  // Relative path → same-origin as the embedding inone dashboard.
5
5
  PRODUCT_ATTRIBUTES_PATH: "/product-attributes/get-attributes",
6
6
  RECOMMENDATION_STRATEGIES_PATH: "/api/recommendation-strategies",
7
7
  RECOMMENDATION_STRATEGIES_PANEL_PATH: "/discovery/recommendation-strategies",
8
- NEWSLETTER_RECOMMENDATIONS_PATH: "/newsletter/recommendations"
9
- }, c = "migrate-strategies", d = "template", m = {
8
+ NEWSLETTER_RECOMMENDATIONS_PATH: "/newsletter/recommendations",
9
+ MIGRATE_STRATEGIES_PATH: "/newsletter/recommendations/migrate-strategies",
10
+ // The template route narrows the recommendations resource before the action: the id
11
+ // travels in the body, not the path.
12
+ TEMPLATE_MIGRATE_STRATEGIES_PATH: "/newsletter/recommendations/template/migrate-strategies"
13
+ }, c = {
14
+ campaign: a.MIGRATE_STRATEGIES_PATH,
15
+ template: a.TEMPLATE_MIGRATE_STRATEGIES_PATH
16
+ }, d = {
10
17
  CLIENT_ID: "clientId"
11
- }, p = () => {
12
- const e = r();
18
+ }, m = () => {
19
+ const e = n();
13
20
  return [
14
21
  {
15
22
  id: 11,
@@ -72,75 +79,74 @@ const l = {
72
79
  path: "top-sellers"
73
80
  }
74
81
  ];
75
- }, v = ["discount", "omnibus_price", "omnibus_discount", "price", "original_price"], h = [
82
+ }, p = ["discount", "omnibus_price", "omnibus_discount", "price", "original_price"], T = [
76
83
  { text: "before the amount", value: "0" },
77
84
  { text: "after the amount", value: "1" }
78
- ], x = [
85
+ ], v = [
79
86
  { text: "dot(.)", value: "." },
80
87
  { text: "comma(,)", value: "," },
81
88
  { text: "space( )", value: " " }
82
- ], E = [
89
+ ], A = [
83
90
  { text: "0", value: "0" },
84
91
  { text: "1", value: "1" },
85
92
  { text: "2", value: "2" },
86
93
  { text: "3", value: "3" },
87
94
  { text: "4", value: "4" },
88
95
  { text: "5", value: "5" }
89
- ], a = "||", t = [
96
+ ], r = "||", t = [
90
97
  { text: "is exactly", value: "=" },
91
98
  { text: "contains", value: "~" },
92
99
  { text: "does not contain", value: "!~" },
93
- { text: "any of", value: a }
94
- ], n = [
100
+ { text: "any of", value: r }
101
+ ], o = [
95
102
  { text: "is exactly", value: "=" },
96
103
  { text: "is not exactly", value: "!==" },
97
104
  { text: "contains", value: "~" },
98
105
  { text: "does not contain", value: "!~" },
99
- { text: "any of", value: a }
100
- ], o = [
106
+ { text: "any of", value: r }
107
+ ], s = [
101
108
  { text: "is equal to", value: "=" },
102
109
  { text: "is greater than", value: ">" },
103
110
  { text: "is less than", value: "<" }
104
- ], s = [
111
+ ], i = [
105
112
  { text: "is equal to", value: "=" },
106
113
  { text: "after", value: ">" },
107
114
  { text: "before", value: "<" }
108
- ], i = [
115
+ ], u = [
109
116
  { text: "true", value: "==" },
110
117
  { text: "false", value: "!=" }
111
- ], T = (e) => {
118
+ ], E = (e) => {
112
119
  if (!e)
113
120
  return t;
114
121
  switch (e) {
115
122
  case "Boolean":
116
- return i;
123
+ return u;
117
124
  case "Date":
118
- return s;
125
+ return i;
119
126
  case "Number":
120
- return o;
127
+ return s;
121
128
  case "String":
122
129
  return t;
123
130
  case "Strings":
124
- return n;
131
+ return o;
125
132
  default:
126
133
  return t;
127
134
  }
128
135
  };
129
136
  export {
130
- c as MIGRATE_STRATEGIES_SEGMENT,
131
- a as OP_ANY_OF,
132
- v as PriceAttributes,
133
- m as QUERY_PARAMS,
134
- d as TEMPLATE_MIGRATION_SCOPE_SEGMENT,
135
- l as URLS,
136
- E as currencyDecimalCounts,
137
- h as currencyLocationMaps,
138
- x as currencyOperators,
139
- T as getOperatorOptions,
140
- p as getRecommendationFeedSourceMaps,
141
- n as operatorOptionsForArrayOfStrings,
142
- i as operatorOptionsForBooleans,
143
- s as operatorOptionsForDates,
144
- o as operatorOptionsForNumbers,
137
+ c as MIGRATION_PATHS,
138
+ r as OP_ANY_OF,
139
+ p as PriceAttributes,
140
+ d as QUERY_PARAMS,
141
+ a as URLS,
142
+ A as currencyDecimalCounts,
143
+ T as currencyLocationMaps,
144
+ v as currencyOperators,
145
+ E as getOperatorOptions,
146
+ m as getRecommendationFeedSourceMaps,
147
+ o as operatorOptionsForArrayOfStrings,
148
+ u as operatorOptionsForBooleans,
149
+ i as operatorOptionsForDates,
150
+ s as operatorOptionsForNumbers,
145
151
  t as operatorOptionsForStrings
146
152
  };
@@ -19,18 +19,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";
21
21
  import { LOCALE_CONTROL_ID as yt } from "./locale.js";
22
- import { PricePlacementControl as E } from "./pricePlacement.js";
22
+ import { PricePlacementControl as k } from "./pricePlacement.js";
23
23
  import { PRICE_PLACEMENT_CONTROL_ID as _t } from "./pricePlacement.js";
24
- import { ProductCountControl as k } from "./productCount.js";
24
+ import { ProductCountControl as E } from "./productCount.js";
25
25
  import { PRODUCT_COUNT_CONTROL_ID as Rt } from "./productCount.js";
26
- import { ProductLayoutControl as D } from "./productLayout.js";
26
+ import { ProductLayoutControl as F } from "./productLayout.js";
27
27
  import { PRODUCT_LAYOUT_CONTROL_ID as Tt } from "./productLayout.js";
28
- import { ShuffleControl as F } from "./shuffle.js";
28
+ 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
32
  import { setCurrencyAttributes as A, getBlockElement as B, isPartnerManagedBlock as v, updateProductContentInPlace as x, regenerateProductRowsWithStyles as U } from "./utils.js";
33
- import { adjustProductsToSize as kt, formatProductPrice as Dt, getCardComposition as Ft, getCurrentLayout as wt, getMainContainerTbody as At, regenerateMobileProductRows as Bt, updatePricesInPlace as vt, updateSingleProductContent as xt } 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";
34
34
  import { useDebounceFn as f } from "../../../../../node_modules/@vueuse/shared/index.js";
35
35
  const $ = "ui-elements-recommendation-block";
36
36
  class at extends N {
@@ -39,8 +39,6 @@ class at extends N {
39
39
  r(this, "store", R());
40
40
  r(this, "storeUnsubscription", () => {
41
41
  });
42
- // blockId -> fingerprint of the node config as it looked at the last sync.
43
- r(this, "syncedConfigs", /* @__PURE__ */ new Map());
44
42
  // A config change waiting to reach the node config. Deferred so it can ride the
45
43
  // re-render's single apply() — one user action must cost one undo press.
46
44
  r(this, "pendingNodeConfigWrite", null);
@@ -120,7 +118,7 @@ class at extends N {
120
118
  return this.rrsEnabled = p().isFeatureEnabled("reusableRecommendationStrategy"), this._subControls.forEach((e) => {
121
119
  var o;
122
120
  return (o = e == null ? void 0 : e.onDestroy) == null ? void 0 : o.call(e);
123
- }), this.algorithmControl = new T(), this.localeControl = new L(), this.currencyControl = new P(), this.productCountControl = new k(), this.productLayoutControl = new D(), this.filtersControl = new S(), this.shuffleControl = new F(), this.pricePlacementControl = new E(), this.layoutOrientationControl = new O(), this.strategyControl = this.rrsEnabled ? new w() : null, this._subControls.forEach((e) => {
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) => {
124
122
  e && (e.api = this.api);
125
123
  }), `
126
124
  <div class="recommendation-controls-container">
@@ -200,11 +198,19 @@ class at extends N {
200
198
  * fingerprint diff on this hook is the only way to notice (SD-149105).
201
199
  * An unchanged fingerprint means the move came from us, so runtime store
202
200
  * edits are never clobbered (SD-141049).
201
+ *
202
+ * The fingerprint is kept on the block's own store state so deleting the
203
+ * block drops it with the state it describes. A control-owned memo outlived
204
+ * that state and made a re-dropped saved module keep the defaults its wiped
205
+ * state was rebuilt with (SD-150347).
203
206
  */
204
207
  _syncNodeConfigIfChanged(t) {
205
208
  this.pendingNodeConfigWrite && this.pendingNodeConfigWrite.blockId !== t && this._flushPendingNodeConfig();
206
- const e = JSON.stringify(c.getConfig(this.currentNode)), o = this.syncedConfigs.get(t);
207
- this.syncedConfigs.set(t, e), o !== e && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
209
+ const e = this.store.blockStates[t];
210
+ if (!e)
211
+ return;
212
+ const o = JSON.stringify(c.getConfig(this.currentNode)), n = e.syncedConfigFingerprint;
213
+ e.syncedConfigFingerprint = o, n !== o && (this.pendingNodeConfigWrite || this._syncNodeConfigToStore());
208
214
  }
209
215
  _capturePendingNodeConfigWrite() {
210
216
  const t = this.store.currentRecommendationId;
@@ -429,18 +435,18 @@ export {
429
435
  _t as PRICE_PLACEMENT_CONTROL_ID,
430
436
  Rt as PRODUCT_COUNT_CONTROL_ID,
431
437
  Tt as PRODUCT_LAYOUT_CONTROL_ID,
432
- E as PricePlacementControl,
433
- k as ProductCountControl,
434
- D as ProductLayoutControl,
438
+ k as PricePlacementControl,
439
+ E as ProductCountControl,
440
+ F as ProductLayoutControl,
435
441
  at as RecommendationBlockControl,
436
442
  St as SHUFFLE_CONTROL_ID,
437
443
  Lt as STRATEGY_CONTROL_ID,
438
- F as ShuffleControl,
444
+ D as ShuffleControl,
439
445
  w as StrategyControl,
440
- kt as adjustProductsToSize,
441
- Dt as formatProductPrice,
446
+ Et as adjustProductsToSize,
447
+ Ft as formatProductPrice,
442
448
  B as getBlockElement,
443
- Ft as getCardComposition,
449
+ Dt as getCardComposition,
444
450
  wt as getCurrentLayout,
445
451
  At as getMainContainerTbody,
446
452
  v as isPartnerManagedBlock,
@@ -1,5 +1,5 @@
1
- import { getRecommendationFeedSourceMaps as R, getOperatorOptions as D, PriceAttributes as F } from "../../../../enums/extensions/recommendationBlock.js";
2
- import { useRecommendationApi as P } from "../../../../services/recommendationApi.js";
1
+ import { getRecommendationFeedSourceMaps as R, getOperatorOptions as F, PriceAttributes as P } from "../../../../enums/extensions/recommendationBlock.js";
2
+ import { useRecommendationApi as D } from "../../../../services/recommendationApi.js";
3
3
  import { useConfigStore as k } from "../../../../stores/config.js";
4
4
  import { defineStore as L } from "pinia";
5
5
  import "../constants/selectors.js";
@@ -8,11 +8,11 @@ import { CURRENT_CONFIG_VERSION as y, DEFAULT_NODE_CONFIG as N, EXCLUDED_ALGORIT
8
8
  import { getDefaultProducts as C } from "../templates/utils.js";
9
9
  import { generateCompleteFilterQuery as v } from "../utils/filterUtil.js";
10
10
  import { isLegacyStrategyConfig as x } from "../utils/legacyStrategyMigration.js";
11
- import { getPartnerRecommendationParams as z } from "../utils/partnerCustomizations.js";
12
- import { sanitizeProductIds as B } from "../utils/productIds.js";
11
+ import { getPartnerRecommendationParams as B } from "../utils/partnerCustomizations.js";
12
+ import { sanitizeProductIds as z } from "../utils/productIds.js";
13
13
  import { isFilterValid as A } from "../validation/filterSchema.js";
14
14
  import { isConfigValid as O } from "../validation/requiredFields.js";
15
- const m = P();
15
+ const m = D();
16
16
  let f = null, g = null, h = null, S = null;
17
17
  const p = /* @__PURE__ */ new Map();
18
18
  function G() {
@@ -60,6 +60,7 @@ function w() {
60
60
  filterGroup: 1,
61
61
  isInitialized: !1,
62
62
  filterSnapshot: null,
63
+ syncedConfigFingerprint: null,
63
64
  legacyConversionLoading: !1
64
65
  };
65
66
  }
@@ -169,7 +170,7 @@ const E = () => ({
169
170
  getFilterList() {
170
171
  return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
171
172
  let e;
172
- return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : F.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
173
+ return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : P.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
173
174
  text: t.displayName,
174
175
  value: e,
175
176
  type: t.attributeType
@@ -254,7 +255,7 @@ const E = () => ({
254
255
  const r = (o, c) => o === "." || o === "," || o === " " ? o : c, n = {
255
256
  name: e.currencyCode,
256
257
  value: e.currencyCode,
257
- symbol: e.currencyCode,
258
+ symbol: e.currencySymbol,
258
259
  alignment: e.currencyAlignment === "before" ? "0" : "1",
259
260
  decimalCount: String(e.currencyDecimalCount),
260
261
  decimalSeparator: r(e.currencyDecimalSeparator, ","),
@@ -298,7 +299,7 @@ const E = () => ({
298
299
  * Creates a filter with the first available attribute and operator pre-selected.
299
300
  */
300
301
  createDefaultFilter(t, e) {
301
- const [r] = this.getFilterList, [n] = D(r == null ? void 0 : r.type);
302
+ const [r] = this.getFilterList, [n] = F(r == null ? void 0 : r.type);
302
303
  return {
303
304
  type: "standardFilter",
304
305
  attribute: (r == null ? void 0 : r.value) ?? "",
@@ -421,6 +422,15 @@ const E = () => ({
421
422
  this.blockStates[r] && (this.blockStates[r].legacyConversionLoading = !1);
422
423
  }
423
424
  },
425
+ /**
426
+ * Undoes the config half of a conversion whose document write never landed, so the
427
+ * panel and the drawer fall back to "Legacy Strategy" instead of showing an assignment
428
+ * the document never received.
429
+ */
430
+ revertLegacyConversion(t, e) {
431
+ const r = this.blockStates[t];
432
+ r && (r.recommendationConfigs = { ...r.recommendationConfigs, ...e }, this.currentRecommendationId === t && this.configVersion++);
433
+ },
424
434
  removeStrategy() {
425
435
  this.patchCurrentBlockConfig({
426
436
  strategyId: "",
@@ -578,9 +588,9 @@ const E = () => ({
578
588
  details: !0,
579
589
  campaignId: n.variationId
580
590
  };
581
- r.strategy === "manualMerchandising" ? a.productId = B(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), i && (a.filter = i), r.shuffleProducts && (a.shuffle = !0), Object.assign(
591
+ r.strategy === "manualMerchandising" ? a.productId = z(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), i && (a.filter = i), r.shuffleProducts && (a.shuffle = !0), Object.assign(
582
592
  a,
583
- z(n.partnerName, r.strategy)
593
+ B(n.partnerName, r.strategy)
584
594
  );
585
595
  let l;
586
596
  try {
@@ -590,6 +600,15 @@ const E = () => ({
590
600
  }
591
601
  this._setBlockProducts(t, l, c);
592
602
  },
603
+ /**
604
+ * Block-scoped counterpart of `fetchRecommendationProducts`, which only ever serves the
605
+ * selected block. The legacy conversion must refresh the products of the block that
606
+ * started it even after the user selected another one.
607
+ */
608
+ async fetchStrategyProductsForBlock(t) {
609
+ var e;
610
+ (e = this.blockStates[t]) != null && e.recommendationConfigs.strategyId && await this._doFetchStrategyProducts(t);
611
+ },
593
612
  async _doFetchStrategyProducts(t) {
594
613
  const e = (p.get(t) ?? 0) + 1;
595
614
  p.set(t, e);
@@ -602,8 +621,8 @@ const E = () => ({
602
621
  );
603
622
  if (i) {
604
623
  s = parseInt(String(i.size ?? "")) || s;
605
- const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), d = l === -1 ? a : a.slice(0, l), u = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((b) => b && !b.startsWith("user_id=")), I = u.length ? `${d}?${u.join("&")}` : d;
606
- I && (n = await m.fetchRecommendationProductsByUrl(I));
624
+ const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), d = l === -1 ? a : a.slice(0, l), u = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((I) => I && !I.startsWith("user_id=")), b = u.length ? `${d}?${u.join("&")}` : d;
625
+ b && (n = await m.fetchRecommendationProductsByUrl(b));
607
626
  }
608
627
  } catch {
609
628
  n = [];