@useinsider/guido 3.3.1-beta.11641c6 → 3.4.0-beta.14fc097

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 (36) hide show
  1. package/dist/@types/config/schemas.js +1 -1
  2. package/dist/components/Guido.vue.js +1 -1
  3. package/dist/components/Guido.vue2.js +42 -40
  4. package/dist/components/organisms/extensions/recommendation/FilterItem.vue.js +9 -11
  5. package/dist/components/organisms/extensions/recommendation/FilterItem.vue2.js +70 -35
  6. package/dist/components/organisms/header/MiddleSlot.vue.js +7 -7
  7. package/dist/composables/useCortexBlueprintBridge.js +66 -0
  8. package/dist/composables/useEmailTemplateApplier.js +41 -0
  9. package/dist/composables/useGuidoStateBridge.js +48 -0
  10. package/dist/composables/useHtmlValidator.js +53 -47
  11. package/dist/composables/useResponsivePreview.js +1 -1
  12. package/dist/config/migrator/radioButtonMigrator.js +30 -29
  13. package/dist/enums/extensions/recommendationBlock.js +33 -32
  14. package/dist/extensions/Blocks/RadioButton/template.js +6 -6
  15. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +30 -21
  16. package/dist/extensions/Blocks/Recommendation/templates/grid/elementRenderer.js +3 -3
  17. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +3 -3
  18. package/dist/extensions/Blocks/Recommendation/templates/list/elementRenderer.js +3 -3
  19. package/dist/extensions/Blocks/Recommendation/utils/filterUtil.js +25 -12
  20. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +33 -0
  21. package/dist/guido.css +1 -1
  22. package/dist/node_modules/valibot/dist/index.js +252 -329
  23. package/dist/package.json.js +1 -1
  24. package/dist/services/unsubscribeApi.js +6 -6
  25. package/dist/src/composables/useCortexBlueprintBridge.d.ts +25 -0
  26. package/dist/src/composables/useEmailTemplateApplier.d.ts +21 -0
  27. package/dist/src/composables/useGuidoStateBridge.d.ts +22 -0
  28. package/dist/src/enums/extensions/recommendationBlock.d.ts +1 -0
  29. package/dist/src/extensions/Blocks/RadioButton/template.d.ts +1 -1
  30. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +7 -1
  31. package/dist/src/extensions/Blocks/Recommendation/utils/filterUtil.d.ts +2 -0
  32. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +21 -0
  33. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.test.d.ts +1 -0
  34. package/dist/src/stores/guido-email-editor.d.ts +41 -0
  35. package/dist/stores/guido-email-editor.js +20 -0
  36. package/package.json +5 -4
@@ -1,54 +1,56 @@
1
- import { useConfig as L } from "./useConfig.js";
2
- import { TemplateTypes as V } from "../enums/defaults.js";
3
- import { DISPLAY_CONDITIONS_REGEX as _, DISPLAY_CONDITIONS_EXCEPTIONS_REGEX as H, CampaignCouldNotBeSavedKey as P, CanNotMakeAnyChangesForRunningKey as G } from "../enums/html-validator.js";
1
+ import { useConfig as V } from "./useConfig.js";
2
+ import { TemplateTypes as H } from "../enums/defaults.js";
3
+ import { DISPLAY_CONDITIONS_REGEX as P, DISPLAY_CONDITIONS_EXCEPTIONS_REGEX as G, CampaignCouldNotBeSavedKey as M, CanNotMakeAnyChangesForRunningKey as $ } from "../enums/html-validator.js";
4
4
  import { ToasterTypeOptions as c } from "../enums/toaster.js";
5
- import { itemsBlockDynamicVariables as M } from "../extensions/Blocks/Items/enums/productEnums.js";
6
- import { useRecommendationStore as $ } from "../stores/recommendation.js";
7
- import { base64EncodeWithSpecialChars as X } from "../utils/base64.js";
8
- import { useHttp as j } from "./useHttp.js";
9
- import { useToaster as q } from "./useToaster.js";
10
- import { useTranslations as z } from "./useTranslations.js";
11
- const K = /recommendation-id="(\d+)"/g;
12
- function U(a) {
13
- return [...a.matchAll(K)].map((u) => u[1]);
5
+ import { itemsBlockDynamicVariables as j } from "../extensions/Blocks/Items/enums/productEnums.js";
6
+ import { useRecommendationExtensionStore as q } from "../extensions/Blocks/Recommendation/store/recommendation.js";
7
+ import { RecommendationRequiredFieldsKey as X } from "../extensions/Blocks/Recommendation/validation/requiredFields.js";
8
+ import { useRecommendationStore as K } from "../stores/recommendation.js";
9
+ import { base64EncodeWithSpecialChars as z } from "../utils/base64.js";
10
+ import { useHttp as U } from "./useHttp.js";
11
+ import { useToaster as Y } from "./useToaster.js";
12
+ import { useTranslations as Z } from "./useTranslations.js";
13
+ const J = /recommendation-id="(\d+)"/g;
14
+ function Q(a) {
15
+ return [...a.matchAll(J)].map((u) => u[1]);
14
16
  }
15
- function Y(a, u) {
17
+ function ee(a, u) {
16
18
  return u.some((d) => a.startsWith(`${d}_`));
17
19
  }
18
- const ce = () => {
19
- var y, h;
20
- const { showToaster: a } = q(), { post: u } = j(), { config: d } = L(), r = z(), g = $(), p = ((h = (y = d.value) == null ? void 0 : y.partner) == null ? void 0 : h.messageType) === V.transactional, b = async (e) => {
20
+ const ge = () => {
21
+ var h, v;
22
+ const { showToaster: a } = Y(), { post: u } = U(), { config: d } = V(), r = Z(), p = K(), f = q(), y = ((v = (h = d.value) == null ? void 0 : h.partner) == null ? void 0 : v.messageType) === H.transactional, w = async (e) => {
21
23
  const t = await u(
22
24
  "/newsletter/template-library/check-template-html-body",
23
- { html: X(e) }
25
+ { html: z(e) }
24
26
  ), { status: n, message: l } = t.data;
25
27
  return n || a({
26
28
  type: c.Alert,
27
29
  message: n === void 0 ? l : r("newsletter.invalid-url-link-for-toaster")
28
- }), r(P), l === r(G) && a({
30
+ }), r(M), l === r($) && a({
29
31
  type: c.Alert,
30
32
  message: r("newsletter.already-in-progress")
31
33
  }), n;
32
- }, w = (e) => !["if", "endif", "else", "elif", "now"].includes(e.toLowerCase()), S = (e) => ["if", "endif"].includes(e.toLowerCase()), E = (e, s) => {
34
+ }, S = (e) => !["if", "endif", "else", "elif", "now"].includes(e.toLowerCase()), E = (e) => ["if", "endif"].includes(e.toLowerCase()), A = (e, s) => {
33
35
  const t = e.match(/({%(.*?)%})/g);
34
36
  let n = !0;
35
- return t !== null && !p && t.forEach((l) => {
37
+ return t !== null && !y && t.forEach((l) => {
36
38
  const o = l.slice(2, -2).trim().match(/(".*?"|[^"\s]+)(?=\s*|\s*$)/g);
37
39
  if (o && o.length > 0) {
38
40
  const [i] = o;
39
- w(i) && !s.includes(i) && (a({
41
+ S(i) && !s.includes(i) && (a({
40
42
  type: c.Warning,
41
43
  message: r("custom-fields.invalid-custom-fields")
42
44
  }), n = !1);
43
45
  }
44
46
  }), n;
45
- }, A = async (e, s, t) => {
46
- const n = t ? await b(e) : !0;
47
- return E(e, s) && n;
48
- }, I = (e) => e.length > 0 ? !0 : (a({
47
+ }, k = async (e, s, t) => {
48
+ const n = t ? await w(e) : !0;
49
+ return A(e, s) && n;
50
+ }, x = (e) => e.length > 0 ? !0 : (a({
49
51
  type: c.Warning,
50
52
  message: r("newsletter.html-content-is-empty")
51
- }), !1), k = (e) => {
53
+ }), !1), I = (e) => {
52
54
  const s = (e.match(/{/gm) || []).length, t = (e.match(/}/gm) || []).length;
53
55
  return s > t && a({
54
56
  type: c.Warning,
@@ -57,19 +59,19 @@ const ce = () => {
57
59
  type: c.Warning,
58
60
  message: r("custom-fields.missing-opening-braces")
59
61
  }), s === t;
60
- }, x = (e) => {
62
+ }, F = (e) => {
61
63
  const s = e.match(/{{\s*(\w+\s+((\w+\|\w+)|(\w+)))\s*}}/gm) === null;
62
64
  return s || a({
63
65
  type: c.Warning,
64
66
  message: r("custom-fields.invalid-custom-fields")
65
67
  }), s;
66
- }, T = (e, s) => {
68
+ }, R = (e, s) => {
67
69
  const t = e.match(/{{([a-zA-Z0-9_\s]*)}}/gm);
68
- if (t && !p) {
69
- const n = new Set(s.map((i) => i.toLowerCase())), l = U(e), o = [];
70
+ if (t && !y) {
71
+ const n = new Set(s.map((i) => i.toLowerCase())), l = Q(e), o = [];
70
72
  if (t.forEach((i) => {
71
73
  const m = i.slice(2, -2).trim().toLowerCase();
72
- (!n.has(m) || m === "") && !Y(m, l) && o.push(m);
74
+ (!n.has(m) || m === "") && !ee(m, l) && o.push(m);
73
75
  }), o.length > 0) {
74
76
  const i = `
75
77
  <ul>
@@ -83,22 +85,22 @@ const ce = () => {
83
85
  }
84
86
  }
85
87
  return !0;
86
- }, F = (e) => {
88
+ }, T = (e) => {
87
89
  const s = e.match(/{%(.*?)%}/g), t = [];
88
90
  let n = !0;
89
91
  if (s && s.forEach((l) => {
90
- const o = l.match(_), i = l.match(H), m = (o == null ? void 0 : o.join("")) || "";
92
+ const o = l.match(P), i = l.match(G), m = (o == null ? void 0 : o.join("")) || "";
91
93
  (!o || l !== m) && !i && (a({
92
94
  type: c.Alert,
93
95
  message: r("newsletter.display-conditions-invalid-syntax")
94
- }), n = !1), o && o.forEach((f) => {
95
- f.trim() === "=" && (a({
96
+ }), n = !1), o && o.forEach((g) => {
97
+ g.trim() === "=" && (a({
96
98
  type: c.Alert,
97
99
  message: r("custom-conditions.wrong-equality-operators")
98
100
  }), n = !1);
99
- const v = f.match(/^[a-zA-Z]*$/g);
100
- v && v.forEach((C) => {
101
- S(C) && t.push(C);
101
+ const C = g.match(/^[a-zA-Z]*$/g);
102
+ C && C.forEach((b) => {
103
+ E(b) && t.push(b);
102
104
  });
103
105
  });
104
106
  }), t.length) {
@@ -109,25 +111,28 @@ const ce = () => {
109
111
  }), n = !1);
110
112
  }
111
113
  return n;
112
- }, W = (e) => {
114
+ }, B = (e) => {
113
115
  const s = (e.match(/{% /gm) || []).length, t = (e.match(/ %}/gm) || []).length, n = s === t;
114
116
  return n || a({
115
117
  type: c.Warning,
116
118
  message: r("custom-conditions.no-space-after-braces")
117
119
  }), n;
118
- }, N = (e) => (e.match(/({%(.*?)%})/g) || []).filter((t) => t.includes("if")).map((t) => (t.match(/{{.*}}/gm) || []).length).reduce((t, n) => t + n, 0) > 0 ? (a({
120
+ }, W = (e) => (e.match(/({%(.*?)%})/g) || []).filter((t) => t.includes("if")).map((t) => (t.match(/{{.*}}/gm) || []).length).reduce((t, n) => t + n, 0) > 0 ? (a({
119
121
  type: c.Warning,
120
122
  message: r("custom-conditions.no-braces-inside-if-tag")
121
- }), !1) : !0, O = () => g.recommendationConfigs && Object.values(g.recommendationConfigs).find((s) => s.filters.find((t) => t.value === "")) !== void 0 ? (a({
123
+ }), !1) : !0, N = () => f.hasInvalidBlock() ? (a({
124
+ type: c.Alert,
125
+ message: r(X)
126
+ }), !1) : !0, O = () => p.recommendationConfigs && Object.values(p.recommendationConfigs).find((s) => s.filters.find((t) => t.value === "")) !== void 0 ? (a({
122
127
  type: c.Alert,
123
128
  message: r("newsletter.fill-all-necessary-fields")
124
- }), !1) : !0, B = (e) => {
129
+ }), !1) : !0, D = (e) => {
125
130
  const s = /src="[^"]*\.(svg|pst)"/gm;
126
131
  return e.match(s) === null ? !0 : (a({
127
132
  type: c.Alert,
128
133
  message: r("newsletter.invalid-image-type")
129
134
  }), !1);
130
- }, R = (e) => {
135
+ }, L = (e) => {
131
136
  const n = new DOMParser().parseFromString(e, "text/html").querySelectorAll(".checkbox-block-v2");
132
137
  return Array.from(n).find((o) => {
133
138
  var i;
@@ -136,7 +141,7 @@ const ce = () => {
136
141
  type: c.Alert,
137
142
  message: r("unsubscribe-templates.select-checkbox-groups")
138
143
  }), !1) : !0;
139
- }, D = (e) => {
144
+ }, _ = (e) => {
140
145
  const n = new DOMParser().parseFromString(e, "text/html").querySelectorAll(".radio-button-v2");
141
146
  return Array.from(n).find((o) => {
142
147
  var i;
@@ -148,14 +153,15 @@ const ce = () => {
148
153
  };
149
154
  return { validateHtml: async (e, s, t = !1) => {
150
155
  var o, i;
156
+ t && Object.keys(f.blockStates).length > 0 && await f.fetchRecommendationCreateData();
151
157
  const n = [
152
158
  ...s.map((m) => m.value),
153
- ...M,
159
+ ...j,
154
160
  ...((i = (o = d.value) == null ? void 0 : o.template) == null ? void 0 : i.customFieldAttributes) ?? []
155
161
  ];
156
- return await A(e, n, t) && I(e) && k(e) && x(e) && T(e, n) && F(e) && W(e) && N(e) && O() && B(e) && R(e) && D(e);
162
+ return await k(e, n, t) && x(e) && I(e) && F(e) && R(e, n) && T(e) && B(e) && W(e) && N() && O() && D(e) && L(e) && _(e);
157
163
  } };
158
164
  };
159
165
  export {
160
- ce as useHtmlValidator
166
+ ge as useHtmlValidator
161
167
  };
@@ -1,5 +1,5 @@
1
1
  import { useDebounce as p } from "./useDebounce.js";
2
- import { ResponsivePreviewRegex as c, ResponsivePreviewSelectors as v, ResponsivePreviewConfig as a } from "../enums/preview.js";
2
+ import { ResponsivePreviewRegex as c, ResponsivePreviewConfig as a, ResponsivePreviewSelectors as v } from "../enums/preview.js";
3
3
  let i = null, l = null;
4
4
  const { debounce: y } = p(), h = (t) => {
5
5
  if (!t)
@@ -9,14 +9,14 @@ class B {
9
9
  }
10
10
  migrate(e) {
11
11
  try {
12
- const t = this.parser.parseFromString(e, "text/html"), i = t.querySelectorAll("td.radio-button-block"), s = t.querySelectorAll("td.radio-button-v2");
13
- if (i.length === 0 && s.length === 0)
12
+ const t = this.parser.parseFromString(e, "text/html"), s = t.querySelectorAll("td.radio-button-block"), i = t.querySelectorAll("td.radio-button-v2");
13
+ if (s.length === 0 && i.length === 0)
14
14
  return e;
15
15
  let o = !1;
16
- return i.forEach((r) => {
16
+ return s.forEach((r) => {
17
17
  if (r.classList.contains("radio-button-v2"))
18
18
  return;
19
- const n = r.getAttribute("id"), a = this.extractTextFromElement(r, "ins-title"), g = this.extractTextFromElement(r, "ins-description"), c = this.extractTextFromElement(r, "ins-subscribe"), u = this.extractTextFromElement(r, "ins-unsubscribe"), d = this.buildTextBlock(a), p = this.buildTextBlock(g), y = this.buildTextBlock({ ...c, classList: "" }), f = this.buildTextBlock({ ...u, classList: "" }), h = S.replace("{-{-TITLE-}-}", d).replace("{-{-DESCRIPTION-}-}", p).replace("{-{-YES-}-}", y).replace("{-{-NO-}-}", f), m = this.parser.parseFromString(
19
+ const n = r.getAttribute("id"), a = this.extractTextFromElement(r, "ins-title"), g = this.extractTextFromElement(r, "ins-description"), c = this.extractTextFromElement(r, "ins-subscribe"), u = this.extractTextFromElement(r, "ins-unsubscribe"), p = this.buildTextBlock(a), d = this.buildTextBlock(g), y = this.buildTextBlock({ ...c, classList: "" }), f = this.buildTextBlock({ ...u, classList: "" }), h = S.replace("{-{-TITLE-}-}", p).replace("{-{-DESCRIPTION-}-}", d).replace("{-{-YES-}-}", y).replace("{-{-NO-}-}", f), m = this.parser.parseFromString(
20
20
  `<table id="tempDoc"><tbody><tr>${h}</tr></tbody></table>`,
21
21
  "text/html"
22
22
  ).querySelector(".radio-button-v2");
@@ -28,25 +28,26 @@ class B {
28
28
  }
29
29
  healRadioButtonV2(e) {
30
30
  let t = !1;
31
- return e.querySelectorAll("td.radio-button-v2").forEach((i) => {
32
- var p;
33
- const s = i.querySelector("input#radioYes"), o = i.querySelector("input#radioNo");
34
- if (!s || !o)
31
+ return e.querySelectorAll("td.radio-button-v2").forEach((s) => {
32
+ var d;
33
+ s.classList.contains("radio-button-block") || (s.classList.add("radio-button-block"), t = !0);
34
+ const i = s.querySelector("input#radioYes"), o = s.querySelector("input#radioNo");
35
+ if (!i || !o)
35
36
  return;
36
- const r = ((p = s.parentElement) == null ? void 0 : p.querySelector(":scope > p")) || null;
37
- if (!r && !s.hasAttribute("align"))
37
+ const r = ((d = i.parentElement) == null ? void 0 : d.querySelector(":scope > p")) || null;
38
+ if (!r && !i.hasAttribute("align"))
38
39
  return;
39
- const n = s.closest("tr"), a = o.closest("tr");
40
+ const n = i.closest("tr"), a = o.closest("tr");
40
41
  if (!n || !a || n === a || !n.parentNode)
41
42
  return;
42
- const g = (r == null ? void 0 : r.innerHTML.trim()) || "Yes", c = a.cloneNode(!0), u = c.querySelector("input#radioNo"), d = c.querySelector("p");
43
- u && (u.setAttribute("id", "radioYes"), u.removeAttribute("align")), d && (d.innerHTML = g), n.parentNode.replaceChild(c, n), t = !0;
43
+ const g = (r == null ? void 0 : r.innerHTML.trim()) || "Yes", c = a.cloneNode(!0), u = c.querySelector("input#radioNo"), p = c.querySelector("p");
44
+ u && (u.setAttribute("id", "radioYes"), u.removeAttribute("align")), p && (p.innerHTML = g), n.parentNode.replaceChild(c, n), t = !0;
44
45
  }), t;
45
46
  }
46
47
  extractTextFromElement(e, t) {
47
- var p, y;
48
- const i = e.querySelector(`.${t}`);
49
- if (!i)
48
+ var d, y;
49
+ const s = e.querySelector(`.${t}`);
50
+ if (!s)
50
51
  return {
51
52
  text: t === "ins-title" ? "Title" : "Description",
52
53
  isBold: !1,
@@ -55,42 +56,42 @@ class B {
55
56
  styles: "",
56
57
  classList: ""
57
58
  };
58
- const s = i.querySelector("p");
59
- if (!s)
59
+ const i = s.querySelector("p");
60
+ if (!i)
60
61
  return {
61
- text: ((p = i.textContent) == null ? void 0 : p.trim()) || (t === "ins-title" ? "Title" : "Description"),
62
+ text: ((d = s.textContent) == null ? void 0 : d.trim()) || (t === "ins-title" ? "Title" : "Description"),
62
63
  isBold: !1,
63
64
  isItalic: !1,
64
- align: i.getAttribute("align") || "left",
65
+ align: s.getAttribute("align") || "left",
65
66
  styles: "",
66
67
  classList: ""
67
68
  };
68
- const o = ((y = s.textContent) == null ? void 0 : y.trim()) || (t === "ins-title" ? "Title" : "Description"), r = s.getAttribute("style") || "", n = i.getAttribute("align") || s.getAttribute("align") || "left", a = /font-weight\s*:\s*bold/i.test(r) || !!s.querySelector("b, strong"), g = /font-style\s*:\s*italic/i.test(r) || !!s.querySelector("i, em"), c = this.removeStyleProperties(r, ["font-weight", "font-style"]), u = this.convertInlineToBlock(c), d = i.getAttribute("class") || "";
69
+ const o = ((y = i.textContent) == null ? void 0 : y.trim()) || (t === "ins-title" ? "Title" : "Description"), r = i.getAttribute("style") || "", n = s.getAttribute("align") || i.getAttribute("align") || "left", a = /font-weight\s*:\s*bold/i.test(r) || !!i.querySelector("b, strong"), g = /font-style\s*:\s*italic/i.test(r) || !!i.querySelector("i, em"), c = this.removeStyleProperties(r, ["font-weight", "font-style"]), u = this.convertInlineToBlock(c), p = s.getAttribute("class") || "";
69
70
  return {
70
71
  text: o,
71
72
  isBold: a,
72
73
  isItalic: g,
73
74
  align: n,
74
75
  styles: u,
75
- classList: d
76
+ classList: p
76
77
  };
77
78
  }
78
79
  buildTextBlock(e) {
79
80
  let t = e.text;
80
81
  e.isBold && e.isItalic ? t = `<strong path="1,0"><em path="1,0,0">${t}</em></strong>` : e.isBold ? t = `<strong path="1,0">${t}</strong>` : e.isItalic && (t = `<em path="1,0">${t}</em>`);
81
- const i = e.align ? ` align="${e.align}"` : "", s = e.styles ? ` style="${e.styles.replaceAll('"', "'")}"` : "";
82
+ const s = e.align ? ` align="${e.align}"` : "", i = e.styles ? ` style="${e.styles.replaceAll('"', "'")}"` : "";
82
83
  return `
83
- <td class="esd-block-text ${e.classList}" ${i}>
84
- <p path="1" ${s}>
84
+ <td class="esd-block-text ${e.classList}" ${s}>
85
+ <p path="1" ${i}>
85
86
  ${t}
86
87
  </p>
87
88
  </td>
88
89
  `;
89
90
  }
90
91
  removeStyleProperties(e, t) {
91
- return e ? t.reduce((s, o) => {
92
+ return e ? t.reduce((i, o) => {
92
93
  const r = new RegExp(`${o}\\s*:\\s*[^;]*;?`, "gi");
93
- return s.replace(r, "");
94
+ return i.replace(r, "");
94
95
  }, e).replace(/;\s*;/g, ";").replace(/^;|;$/g, "").trim() : "";
95
96
  }
96
97
  convertInlineToBlock(e) {
@@ -100,9 +101,9 @@ class B {
100
101
  return /display\s*:/i.test(t) || (t = t ? `${t}; display: block` : "display: block"), t.replace(/;\s*;/g, ";").replace(/^;|;$/g, "").trim();
101
102
  }
102
103
  }
103
- function q(l) {
104
+ function L(l) {
104
105
  return new B().migrate(l);
105
106
  }
106
107
  export {
107
- q as migrateRadioButton
108
+ L as migrateRadioButton
108
109
  };
@@ -1,10 +1,10 @@
1
- import { useTranslations as a } from "../../composables/useTranslations.js";
2
- const u = {
1
+ import { useTranslations as r } from "../../composables/useTranslations.js";
2
+ const l = {
3
3
  RECOMMENDATION_API_URL: "https://recommendationv2.api.useinsider.com"
4
- }, l = {
4
+ }, c = {
5
5
  CLIENT_ID: "clientId"
6
- }, c = () => {
7
- const e = a();
6
+ }, d = () => {
7
+ const e = r();
8
8
  return [
9
9
  {
10
10
  id: 11,
@@ -67,72 +67,73 @@ const u = {
67
67
  path: "top-sellers"
68
68
  }
69
69
  ];
70
- }, d = ["discount", "omnibus_price", "omnibus_discount", "price", "original_price"], m = [
70
+ }, m = ["discount", "omnibus_price", "omnibus_discount", "price", "original_price"], p = [
71
71
  { text: "before the amount", value: "0" },
72
72
  { text: "after the amount", value: "1" }
73
- ], p = [
73
+ ], v = [
74
74
  { text: "dot(.)", value: "." },
75
75
  { text: "comma(,)", value: "," },
76
76
  { text: "space( )", value: " " }
77
- ], v = [
77
+ ], h = [
78
78
  { text: "0", value: "0" },
79
79
  { text: "1", value: "1" },
80
80
  { text: "2", value: "2" },
81
81
  { text: "3", value: "3" },
82
82
  { text: "4", value: "4" },
83
83
  { text: "5", value: "5" }
84
- ], t = [
84
+ ], a = "||", t = [
85
85
  { text: "is exactly", value: "=" },
86
86
  { text: "contains", value: "~" },
87
87
  { text: "does not contain", value: "!~" },
88
- { text: "any of", value: "||" }
89
- ], r = [
88
+ { text: "any of", value: a }
89
+ ], n = [
90
90
  { text: "is exactly", value: "=" },
91
91
  { text: "is not exactly", value: "!==" },
92
92
  { text: "contains", value: "~" },
93
93
  { text: "does not contain", value: "!~" },
94
- { text: "any of", value: "||" }
95
- ], n = [
94
+ { text: "any of", value: a }
95
+ ], o = [
96
96
  { text: "is equal to", value: "=" },
97
97
  { text: "is greater than", value: ">" },
98
98
  { text: "is less than", value: "<" }
99
- ], o = [
99
+ ], s = [
100
100
  { text: "is equal to", value: "=" },
101
101
  { text: "after", value: ">" },
102
102
  { text: "before", value: "<" }
103
- ], s = [
103
+ ], i = [
104
104
  { text: "true", value: "==" },
105
105
  { text: "false", value: "!=" }
106
- ], h = (e) => {
106
+ ], x = (e) => {
107
107
  if (!e)
108
108
  return t;
109
109
  switch (e) {
110
110
  case "Boolean":
111
- return s;
111
+ return i;
112
112
  case "Date":
113
- return o;
113
+ return s;
114
114
  case "Number":
115
- return n;
115
+ return o;
116
116
  case "String":
117
117
  return t;
118
118
  case "Strings":
119
- return r;
119
+ return n;
120
120
  default:
121
121
  return t;
122
122
  }
123
123
  };
124
124
  export {
125
- d as PriceAttributes,
126
- l as QUERY_PARAMS,
127
- u as URLS,
128
- v as currencyDecimalCounts,
129
- m as currencyLocationMaps,
130
- p as currencyOperators,
131
- h as getOperatorOptions,
132
- c as getRecommendationFeedSourceMaps,
133
- r as operatorOptionsForArrayOfStrings,
134
- s as operatorOptionsForBooleans,
135
- o as operatorOptionsForDates,
136
- n as operatorOptionsForNumbers,
125
+ a as OP_ANY_OF,
126
+ m as PriceAttributes,
127
+ c as QUERY_PARAMS,
128
+ l as URLS,
129
+ h as currencyDecimalCounts,
130
+ p as currencyLocationMaps,
131
+ v as currencyOperators,
132
+ x as getOperatorOptions,
133
+ d as getRecommendationFeedSourceMaps,
134
+ n as operatorOptionsForArrayOfStrings,
135
+ i as operatorOptionsForBooleans,
136
+ s as operatorOptionsForDates,
137
+ o as operatorOptionsForNumbers,
137
138
  t as operatorOptionsForStrings
138
139
  };
@@ -5,7 +5,7 @@ const e = {
5
5
  YES: "Yes",
6
6
  NO: "No"
7
7
  }, d = `
8
- <td align="left" class="radio-button radio-button-v2 esd-block-radio es-p10t es-p10b es-p30r es-p30l">
8
+ <td align="left" class="radio-button-block radio-button-v2 esd-block-radio es-p10t es-p10b es-p30r es-p30l">
9
9
  <table cellpadding="0" cellspacing="0" role="presentation" width="100%">
10
10
  <tbody>
11
11
  <tr>
@@ -75,13 +75,13 @@ const e = {
75
75
  </tbody>
76
76
  </table>
77
77
  </td>
78
- `, a = `
78
+ `, l = `
79
79
  <td
80
80
  align="left"
81
81
  esd-extension-block-id="radio-button-block"
82
82
  esd-handler-name="esd-extension-RadioButtonBlock"
83
83
  class="
84
- radio-button
84
+ radio-button-block
85
85
  radio-button-v2
86
86
  esd-block-ra
87
87
  esd-radio-button-block
@@ -149,10 +149,10 @@ const e = {
149
149
  </table>
150
150
  </td>
151
151
  `;
152
- function l() {
152
+ function a() {
153
153
  return d.replace("{-{-TITLE-}-}", `<p path="1">${e.TITLE}</p>`).replace("{-{-DESCRIPTION-}-}", `<p path="1">${e.DESCRIPTION}</p>`).replace("{-{-YES-}-}", `<p path="1">${e.YES}</p>`).replace("{-{-NO-}-}", `<p path="1">${e.NO}</p>`);
154
154
  }
155
155
  export {
156
- a as default,
157
- l as getDefaultTemplate
156
+ l as default,
157
+ a as getDefaultTemplate
158
158
  };
@@ -1,14 +1,15 @@
1
- import { getRecommendationFeedSourceMaps as S, getOperatorOptions as R, PriceAttributes as y } from "../../../../enums/extensions/recommendationBlock.js";
1
+ import { getRecommendationFeedSourceMaps as g, getOperatorOptions as R, PriceAttributes as y } from "../../../../enums/extensions/recommendationBlock.js";
2
2
  import { useRecommendationApi as C } from "../../../../services/recommendationApi.js";
3
3
  import { useConfigStore as G } from "../../../../stores/config.js";
4
4
  import { defineStore as P } from "pinia";
5
5
  import { DEFAULT_CARDS_IN_ROW as F } from "../constants/layout.js";
6
6
  import { EXCLUDED_ALGORITHM_IDS as D } from "../constants/defaultConfig.js";
7
- import { getDefaultProducts as g } from "../templates/utils.js";
7
+ import { getDefaultProducts as S } from "../templates/utils.js";
8
8
  import { generateCompleteFilterQuery as b } from "../utils/filterUtil.js";
9
9
  import { isFilterValid as w } from "../validation/filterSchema.js";
10
+ import { isConfigValid as v } from "../validation/requiredFields.js";
10
11
  const h = C();
11
- let u = null, m = null, d = null;
12
+ let m = null, u = null, d = null;
12
13
  function k() {
13
14
  return {
14
15
  cardsInRow: F,
@@ -48,7 +49,7 @@ function I() {
48
49
  filterSnapshot: null
49
50
  };
50
51
  }
51
- const v = () => ({
52
+ const N = () => ({
52
53
  recommendationCampaignUrls: {},
53
54
  activePredictiveAlgorithms: [],
54
55
  languages: {},
@@ -57,8 +58,8 @@ const v = () => ({
57
58
  blockStates: {},
58
59
  currentRecommendationId: null,
59
60
  configVersion: 0
60
- }), _ = P("guidoRecommendationExtension", {
61
- state: () => v(),
61
+ }), M = P("guidoRecommendationExtension", {
62
+ state: () => N(),
62
63
  getters: {
63
64
  // ====================================================================
64
65
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -113,7 +114,7 @@ const v = () => ({
113
114
  return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
114
115
  },
115
116
  getActivePredictiveAlgorithms: (t) => {
116
- const e = S(), r = [];
117
+ const e = g(), r = [];
117
118
  return t.activePredictiveAlgorithms.filter((n) => !D.includes(n)).forEach((n) => {
118
119
  r.push(...e.filter((c) => c.id === n));
119
120
  }), r.map((n) => ({
@@ -293,11 +294,11 @@ const v = () => ({
293
294
  // ====================================================================
294
295
  async fetchRecommendationCreateData() {
295
296
  if (!this.activePredictiveAlgorithms.length) {
296
- if (u) {
297
- await u;
297
+ if (m) {
298
+ await m;
298
299
  return;
299
300
  }
300
- u = (async () => {
301
+ m = (async () => {
301
302
  const {
302
303
  activePredictiveAlgorithms: t,
303
304
  languages: e,
@@ -310,26 +311,26 @@ const v = () => ({
310
311
  this.currencyList = r;
311
312
  })();
312
313
  try {
313
- await u;
314
+ await m;
314
315
  } finally {
315
- u = null;
316
+ m = null;
316
317
  }
317
318
  }
318
319
  },
319
320
  async fetchRecommendationFilters() {
320
321
  if (!Object.keys(this.filterList).length) {
321
- if (m) {
322
- await m;
322
+ if (u) {
323
+ await u;
323
324
  return;
324
325
  }
325
- m = (async () => {
326
+ u = (async () => {
326
327
  const t = await h.fetchRecommendationFilters();
327
328
  this.filterList = t;
328
329
  })();
329
330
  try {
330
- await m;
331
+ await u;
331
332
  } finally {
332
- m = null;
333
+ u = null;
333
334
  }
334
335
  }
335
336
  },
@@ -398,6 +399,14 @@ const v = () => ({
398
399
  generateFilterQuery() {
399
400
  return b(this.recommendationConfigs.filters);
400
401
  },
402
+ /**
403
+ * Validation-only check invoked at save-CTA time. Defined as an action
404
+ * (not a getter) so reading it does not register reactive tracking on
405
+ * every block's recommendationConfigs across user edits.
406
+ */
407
+ hasInvalidBlock() {
408
+ return Object.values(this.blockStates).some((t) => !v(t.recommendationConfigs, this));
409
+ },
401
410
  // ====================================================================
402
411
  // Per-Block Product Fetching
403
412
  // ====================================================================
@@ -417,7 +426,7 @@ const v = () => ({
417
426
  },
418
427
  async _doFetchProducts() {
419
428
  var p;
420
- const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = r.filters.filter((l) => l.isValid), c = b(n), i = ((p = S().find((l) => l.key === r.strategy)) == null ? void 0 : p.path) || "", o = G(), s = parseInt(r.size) || 6, a = {
429
+ const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = r.filters.filter((l) => l.isValid), c = b(n), i = ((p = g().find((l) => l.key === r.strategy)) == null ? void 0 : p.path) || "", o = G(), s = parseInt(r.size) || 6, a = {
421
430
  locale: r.language,
422
431
  currency: r.currencySettings.value,
423
432
  partnerName: o.partnerName,
@@ -433,15 +442,15 @@ const v = () => ({
433
442
  f = [];
434
443
  }
435
444
  if (this.blockStates[t]) {
436
- const l = f.length > 0 ? f : g(s);
445
+ const l = f.length > 0 ? f : S(s);
437
446
  l.length < s ? this.blockStates[t].recommendationProducts = [
438
447
  ...l,
439
- ...g(s - l.length)
448
+ ...S(s - l.length)
440
449
  ] : l.length > s ? this.blockStates[t].recommendationProducts = l.slice(0, s) : this.blockStates[t].recommendationProducts = l;
441
450
  }
442
451
  }
443
452
  }
444
453
  });
445
454
  export {
446
- _ as useRecommendationExtensionStore
455
+ M as useRecommendationExtensionStore
447
456
  };