@useinsider/guido 3.19.0-beta.cac604e → 3.19.0-beta.cd75ff0
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.
- package/README.md +1 -0
- package/dist/@types/config/schemas.js +39 -37
- package/dist/components/Guido.vue.js +4 -4
- package/dist/components/Guido.vue2.js +83 -75
- package/dist/components/organisms/AutoSaveController.vue2.js +10 -8
- package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
- package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
- package/dist/components/organisms/header/EditorActions.vue.js +5 -5
- package/dist/components/organisms/header/EditorActions.vue2.js +83 -46
- package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
- package/dist/components/organisms/header/LeftSlot.vue2.js +16 -12
- package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +20 -0
- package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +50 -0
- package/dist/components/wrappers/WpDrawer.vue.js +9 -7
- package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
- package/dist/components/wrappers/WpModal.vue.js +1 -1
- package/dist/components/wrappers/WpModal.vue2.js +4 -3
- package/dist/composables/useAuthError.js +52 -0
- package/dist/composables/useAutoSave.js +44 -42
- package/dist/composables/useHtmlCompiler.js +37 -26
- package/dist/composables/useHtmlValidator.js +2 -0
- package/dist/composables/useHttp.js +64 -54
- package/dist/composables/useLegacyStrategyConversion.js +23 -19
- package/dist/composables/useSave.js +92 -45
- package/dist/composables/useSaveValidation.js +284 -0
- package/dist/composables/useSaveValidationRollout.js +20 -0
- package/dist/composables/useStripo.js +24 -20
- package/dist/composables/useToaster.js +17 -15
- package/dist/composables/validators/useCouponBlockValidator.js +24 -21
- package/dist/composables/validators/useLiquidValidator.js +15 -15
- package/dist/composables/validators/useUnsubscribeBlockValidator.js +34 -27
- package/dist/config/migrator/index.js +14 -13
- package/dist/config/migrator/recommendationPartnerMigrator.js +50 -0
- package/dist/enums/extensions/recommendationBlock.js +30 -29
- package/dist/enums/save-validation.js +4 -0
- package/dist/extensions/Blocks/Recommendation/block.js +54 -88
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +32 -51
- package/dist/extensions/Blocks/Recommendation/utils/partnerScope.js +11 -12
- package/dist/guido.css +1 -1
- package/dist/services/settingsApi.js +11 -0
- package/dist/src/@types/config/schemas.d.ts +4 -0
- package/dist/src/@types/save-validation.d.ts +19 -0
- package/dist/src/components/Guido.vue.d.ts +17 -1
- package/dist/src/components/organisms/base/AuthErrorModal.vue.d.ts +2 -0
- package/dist/src/components/organisms/header/EditorActions.vue.d.ts +17 -1
- package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +17 -1
- package/dist/src/components/organisms/header/RightSlot.vue.d.ts +17 -1
- package/dist/src/components/organisms/validation/ValidationErrorDrawer.vue.d.ts +2 -0
- package/dist/src/components/wrappers/WpDrawer.vue.d.ts +4 -3
- package/dist/src/components/wrappers/WpModal.vue.d.ts +5 -1
- package/dist/src/composables/useAuthError.d.ts +12 -0
- package/dist/src/composables/useAutoSave.d.ts +4 -1
- package/dist/src/composables/useConfig.d.ts +2 -0
- package/dist/src/composables/useHtmlValidator.d.ts +21 -0
- package/dist/src/composables/useHttp.d.ts +2 -0
- package/dist/src/composables/useSave.d.ts +6 -1
- package/dist/src/composables/useSaveValidation.d.ts +6 -0
- package/dist/src/composables/useSaveValidationRollout.d.ts +4 -0
- package/dist/src/composables/validators/useCouponBlockValidator.d.ts +3 -0
- package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +10 -0
- package/dist/src/config/migrator/index.d.ts +2 -1
- package/dist/src/config/migrator/recommendationPartnerMigrator.d.ts +19 -0
- package/dist/src/enums/extensions/recommendationBlock.d.ts +1 -1
- package/dist/src/enums/save-validation.d.ts +27 -0
- package/dist/src/extensions/Blocks/Recommendation/block.d.ts +0 -6
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +0 -5
- package/dist/src/extensions/Blocks/Recommendation/utils/partnerScope.d.ts +13 -7
- package/dist/src/services/settingsApi.d.ts +6 -0
- package/dist/src/stores/config.d.ts +32 -0
- package/dist/src/stores/save-validation.d.ts +22 -0
- package/dist/src/stores/setup-settings.d.ts +4 -0
- package/dist/src/utils/templatePreparation.d.ts +30 -0
- package/dist/stores/config.js +84 -67
- package/dist/stores/save-validation.js +30 -0
- package/dist/stores/setup-settings.js +10 -0
- package/dist/utils/templatePreparation.js +39 -36
- package/package.json +1 -1
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { getIgnoredRecommendationBlockIds as B } from "../config/compiler/utils/recommendationIgnoreUtils.js";
|
|
2
|
+
import { CanNotMakeAnyChangesForRunningKey as k, DISPLAY_CONDITIONS_REGEX as Y, DISPLAY_CONDITIONS_EXCEPTIONS_REGEX as x } from "../enums/html-validator.js";
|
|
3
|
+
import { SaveValidationRule as o } from "../enums/save-validation.js";
|
|
4
|
+
import { ToasterTypeOptions as r } from "../enums/toaster.js";
|
|
5
|
+
import { BLOCK_ROOT_SELECTOR as M } from "../extensions/Blocks/Checkbox/constants/selectors.js";
|
|
6
|
+
import { itemsBlockDynamicVariables as U } from "../extensions/Blocks/Items/enums/productEnums.js";
|
|
7
|
+
import { BLOCK_ROOT_SELECTOR as P } from "../extensions/Blocks/RadioButton/constants/selectors.js";
|
|
8
|
+
import { useRecommendationExtensionStore as W } from "../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
9
|
+
import { getInvalidFields as G, STRATEGY_FIELD_KEY as q, RecommendationAssignStrategyKey as H, RecommendationRequiredFieldsKey as V } from "../extensions/Blocks/Recommendation/validation/requiredFields.js";
|
|
10
|
+
import { useConfigStore as X } from "../stores/config.js";
|
|
11
|
+
import { useDynamicContentStore as j } from "../stores/dynamic-content.js";
|
|
12
|
+
import { useRecommendationStore as z } from "../stores/recommendation.js";
|
|
13
|
+
import { base64EncodeWithSpecialChars as T } from "../utils/base64.js";
|
|
14
|
+
import { escapeHtml as $ } from "../utils/htmlEscape.js";
|
|
15
|
+
import { useTemplatePreparation as Q } from "../utils/templatePreparation.js";
|
|
16
|
+
import { useActionsApi as Z } from "./useActionsApi.js";
|
|
17
|
+
import { useConfig as J } from "./useConfig.js";
|
|
18
|
+
import { useHtmlCompiler as ee } from "./useHtmlCompiler.js";
|
|
19
|
+
import { buildPartnerAttributeNameSet as te, getInvalidDynamicContentTags as ne, getRecommendationBlockIds as ie, findInvalidCustomFields as oe } from "./useHtmlValidator.js";
|
|
20
|
+
import { useHttp as re } from "./useHttp.js";
|
|
21
|
+
import { useTranslations as se } from "./useTranslations.js";
|
|
22
|
+
import { findInvalidCouponBlocks as ae, COUPON_TAG_MODIFIED_KEY as ce } from "./validators/useCouponBlockValidator.js";
|
|
23
|
+
import { findDuplicateUnsubPageTypes as le, countUnsubBlocksWithoutPage as me, EMPTY_BLOCK_KEY as ue } from "./validators/useUnsubscribeBlockValidator.js";
|
|
24
|
+
const de = "newsletter.html-content-is-empty", pe = "custom-fields.missing-closing-braces", ge = "custom-fields.missing-opening-braces", I = "custom-fields.invalid-custom-fields", fe = "newsletter.display-conditions-invalid-syntax", ye = "custom-conditions.wrong-equality-operators", Ee = "custom-conditions.missing-if-endif-tag", Ie = "custom-conditions.no-space-after-braces", Se = "custom-conditions.no-braces-inside-if-tag", _e = "newsletter.fill-all-necessary-fields", Ce = "newsletter.invalid-image-type", he = "unsubscribe-templates.select-checkbox-groups", ke = "unsubscribe-templates.select-radio-button-groups", Te = "newsletter.invalid-url-link-for-toaster", F = "journey-builder.liquid-validation-failed", Fe = "/newsletter/template-library/check-template-html-body", Re = /src="[^"]*\.(svg|pst)"/gm, O = /({%(.*?)%})/g, Oe = ["if", "endif", "else", "elif", "now"], Le = (t) => !Oe.includes(t.toLowerCase()), Ne = (t) => ["if", "endif"].includes(t.toLowerCase());
|
|
25
|
+
function be(t) {
|
|
26
|
+
return ae(t).map((i) => ({
|
|
27
|
+
rule: o.CouponTagModified,
|
|
28
|
+
type: r.Warning,
|
|
29
|
+
key: ce,
|
|
30
|
+
detail: i
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
function Ae(t) {
|
|
34
|
+
return le(t).map((i) => ({
|
|
35
|
+
rule: o.DuplicateUnsubBlock,
|
|
36
|
+
type: r.Error,
|
|
37
|
+
key: i.messageKey
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
function ve(t) {
|
|
41
|
+
return Array.from({ length: me(t) }, () => ({
|
|
42
|
+
rule: o.UnsubBlockMissingTemplate,
|
|
43
|
+
type: r.Warning,
|
|
44
|
+
key: ue
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
function De(t, i) {
|
|
48
|
+
const n = t.match(O);
|
|
49
|
+
if (!n)
|
|
50
|
+
return [];
|
|
51
|
+
const l = [];
|
|
52
|
+
return n.forEach((u) => {
|
|
53
|
+
const c = u.slice(2, -2).trim().match(/(".*?"|[^"\s]+)(?=\s*|\s*$)/g);
|
|
54
|
+
if (c && c.length > 0) {
|
|
55
|
+
const [d] = c;
|
|
56
|
+
Le(d) && !i.includes(d) && l.push({
|
|
57
|
+
rule: o.CustomFieldScript,
|
|
58
|
+
type: r.Warning,
|
|
59
|
+
key: I,
|
|
60
|
+
detail: d
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}), l;
|
|
64
|
+
}
|
|
65
|
+
function Ke(t) {
|
|
66
|
+
return t.length > 0 ? [] : [{ rule: o.EmptyHtml, type: r.Warning, key: de }];
|
|
67
|
+
}
|
|
68
|
+
function we(t) {
|
|
69
|
+
const i = (t.match(/{/gm) || []).length, n = (t.match(/}/gm) || []).length;
|
|
70
|
+
return i > n ? [{
|
|
71
|
+
rule: o.MismatchedBraces,
|
|
72
|
+
type: r.Warning,
|
|
73
|
+
key: pe
|
|
74
|
+
}] : i < n ? [{
|
|
75
|
+
rule: o.MismatchedBraces,
|
|
76
|
+
type: r.Warning,
|
|
77
|
+
key: ge
|
|
78
|
+
}] : [];
|
|
79
|
+
}
|
|
80
|
+
function Be(t) {
|
|
81
|
+
return ne(t).map((i) => ({
|
|
82
|
+
rule: o.InvalidDynamicTag,
|
|
83
|
+
type: r.Warning,
|
|
84
|
+
key: I,
|
|
85
|
+
detail: i
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
function Ye(t, i, n, l) {
|
|
89
|
+
const u = ie(t);
|
|
90
|
+
return oe(t, i, u, n, l).map((c) => ({
|
|
91
|
+
rule: o.InvalidCustomField,
|
|
92
|
+
type: r.Error,
|
|
93
|
+
key: I,
|
|
94
|
+
detail: c
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
function xe(t) {
|
|
98
|
+
const i = t.match(/{%(.*?)%}/g), n = [], l = [];
|
|
99
|
+
if (i && i.forEach((u) => {
|
|
100
|
+
const c = u.match(Y), d = u.match(x), E = (c == null ? void 0 : c.join("")) || "";
|
|
101
|
+
(!c || u !== E) && !d && l.push({
|
|
102
|
+
rule: o.ConditionsSyntax,
|
|
103
|
+
type: r.Error,
|
|
104
|
+
key: fe,
|
|
105
|
+
detail: u
|
|
106
|
+
}), c && c.forEach((g) => {
|
|
107
|
+
g.trim() === "=" && l.push({
|
|
108
|
+
rule: o.WrongEqualityOperator,
|
|
109
|
+
type: r.Error,
|
|
110
|
+
key: ye
|
|
111
|
+
}), (g.match(/^[a-zA-Z]*$/g) ?? []).forEach((f) => {
|
|
112
|
+
Ne(f) && n.push(f);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
}), n.length) {
|
|
116
|
+
const u = n.filter((d) => d === "if").length, c = n.filter((d) => d === "endif").length;
|
|
117
|
+
u !== c && l.push({
|
|
118
|
+
rule: o.MissingIfEndif,
|
|
119
|
+
type: r.Error,
|
|
120
|
+
key: Ee
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return l;
|
|
124
|
+
}
|
|
125
|
+
function Me(t) {
|
|
126
|
+
const i = (t.match(/{% /gm) || []).length, n = (t.match(/ %}/gm) || []).length;
|
|
127
|
+
return i === n ? [] : [{
|
|
128
|
+
rule: o.ConditionTagSpacing,
|
|
129
|
+
type: r.Warning,
|
|
130
|
+
key: Ie
|
|
131
|
+
}];
|
|
132
|
+
}
|
|
133
|
+
function Ue(t) {
|
|
134
|
+
return (t.match(O) || []).filter((n) => n.includes("if")).map((n) => (n.match(/{{.*}}/gm) || []).length).reduce((n, l) => n + l, 0) === 0 ? [] : [{
|
|
135
|
+
rule: o.BracesInsideIfTag,
|
|
136
|
+
type: r.Warning,
|
|
137
|
+
key: Se
|
|
138
|
+
}];
|
|
139
|
+
}
|
|
140
|
+
function Pe(t) {
|
|
141
|
+
return (t.match(Re) ?? []).map((i) => ({
|
|
142
|
+
rule: o.InvalidImageType,
|
|
143
|
+
type: r.Error,
|
|
144
|
+
key: Ce,
|
|
145
|
+
detail: i
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
function R(t, i, n, l) {
|
|
149
|
+
const u = new DOMParser().parseFromString(t, "text/html");
|
|
150
|
+
return Array.from(u.querySelectorAll(i)).filter((c) => {
|
|
151
|
+
var d;
|
|
152
|
+
return !((d = c.id) != null && d.trim());
|
|
153
|
+
}).map(() => ({ rule: n, type: r.Error, key: l }));
|
|
154
|
+
}
|
|
155
|
+
const dt = () => {
|
|
156
|
+
const { config: t, isFeatureEnabled: i } = J(), n = se(), { post: l } = re(), { getCompiledEmail: u, getTemplateData: c } = Z(), { compileHtml: d } = ee(), { hydrateRecommendationStore: E } = Q(), g = j(), f = z(), y = W(), L = X(), N = (e) => ({
|
|
157
|
+
rule: e.rule,
|
|
158
|
+
type: e.type,
|
|
159
|
+
detail: e.detail,
|
|
160
|
+
message: "key" in e ? n(e.key) : $(e.message)
|
|
161
|
+
}), b = async (e) => {
|
|
162
|
+
if (e.size === 0)
|
|
163
|
+
return /* @__PURE__ */ new Set();
|
|
164
|
+
try {
|
|
165
|
+
await y.fetchRecommendationFilters();
|
|
166
|
+
} catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
return te(y.filterList);
|
|
170
|
+
}, A = async (e) => {
|
|
171
|
+
try {
|
|
172
|
+
const s = await l(Fe, { html: T(e) }), { status: a, message: m } = s.data, p = [];
|
|
173
|
+
return a || p.push({
|
|
174
|
+
rule: o.InvalidLinks,
|
|
175
|
+
type: r.Error,
|
|
176
|
+
// status===undefined means a bare message instead of a boolean; surface it,
|
|
177
|
+
// but fall back to the canned key when it's missing so a malformed body
|
|
178
|
+
// never renders a literal 'undefined' row (SD-147430).
|
|
179
|
+
...a === void 0 && m ? { message: m } : { key: Te }
|
|
180
|
+
}), m === n(k) && p.push({
|
|
181
|
+
rule: o.LinkCheckInProgress,
|
|
182
|
+
type: r.Error,
|
|
183
|
+
key: k
|
|
184
|
+
}), p;
|
|
185
|
+
} catch (s) {
|
|
186
|
+
return console.warn("Link-check collector failed; skipping the link rule.", s), [];
|
|
187
|
+
}
|
|
188
|
+
}, v = async (e) => {
|
|
189
|
+
try {
|
|
190
|
+
const s = await l("/newsletter/contents/validate-syntax", [{
|
|
191
|
+
identifier: "default",
|
|
192
|
+
syntax: "liquid",
|
|
193
|
+
contents: {
|
|
194
|
+
subject: null,
|
|
195
|
+
preheader: null,
|
|
196
|
+
html: T(e),
|
|
197
|
+
ampHtml: null
|
|
198
|
+
}
|
|
199
|
+
}]);
|
|
200
|
+
if (!Array.isArray(s.data)) {
|
|
201
|
+
const m = s.data;
|
|
202
|
+
return [{
|
|
203
|
+
rule: o.LiquidSyntax,
|
|
204
|
+
type: r.Warning,
|
|
205
|
+
message: m.message ?? n(F)
|
|
206
|
+
}];
|
|
207
|
+
}
|
|
208
|
+
const [a] = s.data;
|
|
209
|
+
return Object.values((a == null ? void 0 : a.errors) ?? {}).map((m) => ({
|
|
210
|
+
rule: o.LiquidSyntax,
|
|
211
|
+
type: r.Warning,
|
|
212
|
+
message: m.replace(/^line \d+:\s*/, "")
|
|
213
|
+
}));
|
|
214
|
+
} catch (s) {
|
|
215
|
+
if (s != null && s.authReported)
|
|
216
|
+
throw s;
|
|
217
|
+
return [{
|
|
218
|
+
rule: o.LiquidSyntax,
|
|
219
|
+
type: r.Error,
|
|
220
|
+
message: n(F)
|
|
221
|
+
}];
|
|
222
|
+
}
|
|
223
|
+
}, D = () => {
|
|
224
|
+
const e = Object.values(y.blockStates).map((a) => G(a.recommendationConfigs, y)).filter((a) => a.length > 0).map((a) => {
|
|
225
|
+
const m = a.every((p) => p === q);
|
|
226
|
+
return {
|
|
227
|
+
rule: o.RecommendationRequiredFields,
|
|
228
|
+
type: m ? r.Warning : r.Error,
|
|
229
|
+
key: m ? H : V
|
|
230
|
+
};
|
|
231
|
+
}), s = (f.recommendationConfigs ?? []).filter((a) => a.filters.some((m) => m.value === "")).map(() => ({
|
|
232
|
+
rule: o.RecommendationFilters,
|
|
233
|
+
type: r.Error,
|
|
234
|
+
key: _e
|
|
235
|
+
}));
|
|
236
|
+
return [...e, ...s];
|
|
237
|
+
}, K = async (e, s) => {
|
|
238
|
+
var C, h;
|
|
239
|
+
const a = [
|
|
240
|
+
...s.map((w) => w.value),
|
|
241
|
+
...U,
|
|
242
|
+
...((h = (C = t.value) == null ? void 0 : C.template) == null ? void 0 : h.customFieldAttributes) ?? []
|
|
243
|
+
], m = B(e), p = await b(m), { isTransactional: _ } = L;
|
|
244
|
+
return [
|
|
245
|
+
...await A(e),
|
|
246
|
+
..._ ? [] : De(e, a),
|
|
247
|
+
...Ke(e),
|
|
248
|
+
...we(e),
|
|
249
|
+
...Be(e),
|
|
250
|
+
..._ ? [] : Ye(e, a, m, p),
|
|
251
|
+
...xe(e),
|
|
252
|
+
...Me(e),
|
|
253
|
+
...Ue(e),
|
|
254
|
+
...D(),
|
|
255
|
+
...Pe(e),
|
|
256
|
+
...R(
|
|
257
|
+
e,
|
|
258
|
+
M,
|
|
259
|
+
o.CheckboxUnsubGroup,
|
|
260
|
+
he
|
|
261
|
+
),
|
|
262
|
+
...R(
|
|
263
|
+
e,
|
|
264
|
+
P,
|
|
265
|
+
o.RadioButtonUnsubGroup,
|
|
266
|
+
ke
|
|
267
|
+
)
|
|
268
|
+
];
|
|
269
|
+
}, S = async (e, s) => [
|
|
270
|
+
...be(e),
|
|
271
|
+
...Ae(e),
|
|
272
|
+
...ve(e),
|
|
273
|
+
...i("liquidSyntax") ? await v(e) : await K(e, s)
|
|
274
|
+
].map(N);
|
|
275
|
+
return { collectSaveValidationErrors: S, validateCurrentTemplate: async () => {
|
|
276
|
+
const { html: e } = await c();
|
|
277
|
+
await E(e);
|
|
278
|
+
const { html: s } = await u({ minimize: !0, resetDataSavedFlag: !1 }), { compiledHtml: a } = d(s);
|
|
279
|
+
return S(a, g.getSelectedDynamicContentList);
|
|
280
|
+
} };
|
|
281
|
+
};
|
|
282
|
+
export {
|
|
283
|
+
dt as useSaveValidation
|
|
284
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useSettingsApi as l } from "../services/settingsApi.js";
|
|
2
|
+
import { useSetupSettingsStore as s } from "../stores/setup-settings.js";
|
|
3
|
+
import { computed as a } from "vue";
|
|
4
|
+
let o = null;
|
|
5
|
+
const m = () => {
|
|
6
|
+
const t = s();
|
|
7
|
+
return { isEnabled: a(() => t.isEmailAutoSaveEnabled), loadRollout: () => t.isLoaded ? Promise.resolve() : (o ?? (o = l().getSetupSettings().then(({ isEmailAutoSaveEnabled: e }) => {
|
|
8
|
+
t.$patch({
|
|
9
|
+
isEmailAutoSaveEnabled: !!Number(e ?? 0),
|
|
10
|
+
isLoaded: !0
|
|
11
|
+
});
|
|
12
|
+
}).catch((e) => {
|
|
13
|
+
console.warn("Failed to load setup settings; soft-save stays off.", e);
|
|
14
|
+
}).finally(() => {
|
|
15
|
+
o = null;
|
|
16
|
+
})), o) };
|
|
17
|
+
};
|
|
18
|
+
export {
|
|
19
|
+
m as useSaveValidationRollout
|
|
20
|
+
};
|
|
@@ -17,21 +17,21 @@ import { buildMergeTagEntries as W, flattenDynamicContentList as Y } from "../ut
|
|
|
17
17
|
import Z from "../package.json.js";
|
|
18
18
|
let n = null;
|
|
19
19
|
const he = () => {
|
|
20
|
-
const { features: c, template: u, isFeatureEnabled:
|
|
20
|
+
const { features: c, template: u, isFeatureEnabled: p } = H(), { handleError: m, showToaster: v } = G(), { getToken: B, getCustomFonts: M, getSyncModulesStatus: T } = K(), { handleEvent: F } = z(), { handleModuleAdd: A } = j(), { getStripoBlocksConfig: V } = O(), { getStripoNotifications: _ } = $(), f = () => n || (n = new Promise((r, s) => {
|
|
21
21
|
var d;
|
|
22
22
|
if (document.getElementById("UiEditorScript")) {
|
|
23
|
-
|
|
23
|
+
r();
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
-
const o = Z.guido,
|
|
27
|
-
e.id = "UiEditorScript", e.type = "module", e.src =
|
|
28
|
-
e.remove(), s(new Error(`Failed to load Stripo UIEditor script from S3: ${
|
|
26
|
+
const o = Z.guido, i = `https://email-static.useinsider.com/guido/${(d = o == null ? void 0 : o.stripo) == null ? void 0 : d.version}/UIEditor.js`, e = document.createElement("script");
|
|
27
|
+
e.id = "UiEditorScript", e.type = "module", e.src = i, e.onload = () => r(), e.onerror = () => {
|
|
28
|
+
e.remove(), s(new Error(`Failed to load Stripo UIEditor script from S3: ${i}`));
|
|
29
29
|
}, document.body.appendChild(e);
|
|
30
30
|
}), n.catch(() => {
|
|
31
31
|
n = null;
|
|
32
|
-
}), n), D = async (
|
|
32
|
+
}), n), D = async (r, s, o, a = [], i = !1) => {
|
|
33
33
|
var y, E, h, C;
|
|
34
|
-
const e = k(), { html: d, css: R } =
|
|
34
|
+
const e = k(), { html: d, css: R } = r, { baseBlocks: g, extensions: P } = await V(), S = ((y = c.value) == null ? void 0 : y.displayConditions) ?? !0, U = ((E = c.value) == null ? void 0 : E.modulesDisabled) ?? !1, I = !!d || (((h = u.value) == null ? void 0 : h.forceRecreate) ?? !1), q = "https://email-static.useinsider.com https://edge.fullstory.com https://rs.fullstory.com";
|
|
35
35
|
w().importCss(), await window.UIEditor.initEditor(
|
|
36
36
|
document.querySelector("#guido-editor"),
|
|
37
37
|
{
|
|
@@ -45,7 +45,7 @@ const he = () => {
|
|
|
45
45
|
mobileViewButtonSelector: ".guido__view-option-selection-mobile",
|
|
46
46
|
desktopViewButtonSelector: ".guido__view-option-selection-desktop",
|
|
47
47
|
codeEditorButtonSelector: "#guido__code-button",
|
|
48
|
-
customAppearanceMergetags: !
|
|
48
|
+
customAppearanceMergetags: !p("liquidSyntax"),
|
|
49
49
|
customAppearanceMergetagsBorderColor: "#f1f3fe",
|
|
50
50
|
customAppearanceMergetagsBackgroundColor: "#f1f3fe",
|
|
51
51
|
customViewStyles: Q,
|
|
@@ -53,7 +53,7 @@ const he = () => {
|
|
|
53
53
|
customConditionsEnabled: S,
|
|
54
54
|
enableXSSSecurity: !0,
|
|
55
55
|
modulesDisabled: U,
|
|
56
|
-
syncModulesEnabled:
|
|
56
|
+
syncModulesEnabled: i,
|
|
57
57
|
messageSettingsEnabled: !0,
|
|
58
58
|
displayGmailAnnotations: !0,
|
|
59
59
|
displayHiddenPreheader: !1,
|
|
@@ -74,16 +74,16 @@ const he = () => {
|
|
|
74
74
|
entries: W(
|
|
75
75
|
o.preselectedDynamicContentList,
|
|
76
76
|
Y((C = u.value) == null ? void 0 : C.dynamicContentList),
|
|
77
|
-
|
|
77
|
+
p("liquidSyntax")
|
|
78
78
|
)
|
|
79
79
|
}
|
|
80
80
|
],
|
|
81
81
|
async onTokenRefreshRequest(t) {
|
|
82
82
|
try {
|
|
83
|
-
const l = await
|
|
83
|
+
const l = await B();
|
|
84
84
|
t(l);
|
|
85
85
|
} catch (l) {
|
|
86
|
-
|
|
86
|
+
m(l, "Failed to refresh token");
|
|
87
87
|
}
|
|
88
88
|
},
|
|
89
89
|
onTemplateLoaded() {
|
|
@@ -93,7 +93,7 @@ const he = () => {
|
|
|
93
93
|
e.hasChanges = !1;
|
|
94
94
|
}, 1e3);
|
|
95
95
|
} catch (t) {
|
|
96
|
-
|
|
96
|
+
m(t, "Failed to load custom interface appearance");
|
|
97
97
|
}
|
|
98
98
|
},
|
|
99
99
|
onCodeEditorVisibilityChanged(t) {
|
|
@@ -111,27 +111,31 @@ const he = () => {
|
|
|
111
111
|
onEvent: F,
|
|
112
112
|
onModuleAdd: A,
|
|
113
113
|
notifications: _(),
|
|
114
|
+
// Stripo deselects the block on any click outside the canvas, so every surface
|
|
115
|
+
// that belongs to the block's own flow has to be listed here (SD-153273).
|
|
114
116
|
ignoreClickOutsideSelectors: [
|
|
115
117
|
"#guido-dynamic-content-modal",
|
|
116
118
|
".in-on-board-wrapper",
|
|
117
|
-
".in-drawer__container"
|
|
119
|
+
".in-drawer__container",
|
|
120
|
+
".in-modal-v2-wrapper",
|
|
121
|
+
".in-toasts-wrapper"
|
|
118
122
|
],
|
|
119
123
|
extensions: P,
|
|
120
124
|
localePatch: J
|
|
121
125
|
}
|
|
122
126
|
);
|
|
123
127
|
};
|
|
124
|
-
return { initPlugin: async (
|
|
128
|
+
return { initPlugin: async (r, s, o) => {
|
|
125
129
|
const a = k();
|
|
126
130
|
try {
|
|
127
131
|
await f();
|
|
128
|
-
const [
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
const [i, e] = await Promise.all([
|
|
133
|
+
M(),
|
|
134
|
+
T()
|
|
131
135
|
]);
|
|
132
|
-
a.syncModulesEnabled = e, await D(
|
|
136
|
+
a.syncModulesEnabled = e, await D(r, s, o, i, e);
|
|
133
137
|
} catch {
|
|
134
|
-
a.loadingStatus = !1,
|
|
138
|
+
a.loadingStatus = !1, v({
|
|
135
139
|
type: X.Error,
|
|
136
140
|
message: b["An error has occurred. Please report the error code to support."],
|
|
137
141
|
actionButton: {
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
import { ToasterTypeOptions as T } from "../enums/toaster.js";
|
|
2
|
-
import { useToasterStore as
|
|
3
|
-
import { nextTick as
|
|
2
|
+
import { useToasterStore as u } from "../stores/toaster.js";
|
|
3
|
+
import { nextTick as c } from "vue";
|
|
4
4
|
const s = /* @__PURE__ */ new WeakMap(), p = () => {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
5
|
+
const t = u(), o = () => {
|
|
6
|
+
const e = s.get(t);
|
|
7
|
+
e && (clearTimeout(e), s.delete(t));
|
|
8
8
|
};
|
|
9
|
-
function
|
|
10
|
-
o(),
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
function i(e = { message: "" }) {
|
|
10
|
+
o(), t.hideToaster(), c(() => {
|
|
11
|
+
t.showToaster(e), t.shouldAutoHide && s.set(t, setTimeout(() => {
|
|
12
|
+
t.hideToaster(), o();
|
|
13
13
|
}, 6e3));
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
|
-
function
|
|
17
|
-
o(),
|
|
16
|
+
function n() {
|
|
17
|
+
o(), t.hideToaster();
|
|
18
18
|
}
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
function a(e, r) {
|
|
20
|
+
if (e != null && e.authReported)
|
|
21
|
+
return;
|
|
22
|
+
const m = e instanceof Error ? e.message : String(e);
|
|
23
|
+
i({ type: T.Error, message: `${r}: ${m}` });
|
|
22
24
|
}
|
|
23
|
-
return { showToaster:
|
|
25
|
+
return { showToaster: i, hideToaster: n, handleError: a };
|
|
24
26
|
};
|
|
25
27
|
export {
|
|
26
28
|
p as useToaster
|
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
import { ToasterTypeOptions as
|
|
2
|
-
import { COUPON_PLACEHOLDER_DEFAULT as
|
|
3
|
-
import { useToaster as
|
|
4
|
-
import { useTranslations as
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
]),
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
import { ToasterTypeOptions as n } from "../../enums/toaster.js";
|
|
2
|
+
import { COUPON_PLACEHOLDER_DEFAULT as s, COUPON_PLACEHOLDER_LIQUID as a } from "../../extensions/Blocks/CouponBlock/template.js";
|
|
3
|
+
import { useToaster as i } from "../useToaster.js";
|
|
4
|
+
import { useTranslations as l } from "../useTranslations.js";
|
|
5
|
+
const c = /* @__PURE__ */ new Set([
|
|
6
|
+
s,
|
|
7
|
+
a
|
|
8
|
+
]), p = "newsletter.coupon-tag-modified";
|
|
9
|
+
function u(r) {
|
|
10
|
+
const e = new DOMParser().parseFromString(r, "text/html");
|
|
11
|
+
return Array.from(e.querySelectorAll(".coupon-block")).map((o) => {
|
|
12
|
+
var t;
|
|
13
|
+
return ((t = o.textContent) == null ? void 0 : t.trim()) ?? "";
|
|
14
|
+
}).filter((o) => !c.has(o));
|
|
15
|
+
}
|
|
16
|
+
const T = () => {
|
|
17
|
+
const { showToaster: r } = i(), e = l();
|
|
18
|
+
return { validateCouponBlockTags: (t) => u(t).length > 0 ? (r({
|
|
19
|
+
type: n.Warning,
|
|
20
|
+
message: e(p)
|
|
21
|
+
}), !1) : !0 };
|
|
21
22
|
};
|
|
22
23
|
export {
|
|
23
|
-
|
|
24
|
+
p as COUPON_TAG_MODIFIED_KEY,
|
|
25
|
+
u as findInvalidCouponBlocks,
|
|
26
|
+
T as useCouponBlockValidator
|
|
24
27
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { ToasterTypeOptions as
|
|
1
|
+
import { ToasterTypeOptions as r } from "../../enums/toaster.js";
|
|
2
2
|
import { base64EncodeWithSpecialChars as u } from "../../utils/base64.js";
|
|
3
3
|
import { useHttp as d } from "../useHttp.js";
|
|
4
|
-
import { useToaster as
|
|
5
|
-
import { useTranslations as
|
|
4
|
+
import { useToaster as p } from "../useToaster.js";
|
|
5
|
+
import { useTranslations as c } from "../useTranslations.js";
|
|
6
6
|
const v = () => {
|
|
7
|
-
const { post: i } = d(), { showToaster:
|
|
7
|
+
const { post: i } = d(), { showToaster: t } = p(), s = c();
|
|
8
8
|
return { validateLiquidSyntax: async (o) => {
|
|
9
9
|
try {
|
|
10
|
-
const
|
|
10
|
+
const e = await i("/newsletter/contents/validate-syntax", [{
|
|
11
11
|
identifier: "default",
|
|
12
12
|
syntax: "liquid",
|
|
13
13
|
contents: {
|
|
@@ -17,21 +17,21 @@ const v = () => {
|
|
|
17
17
|
ampHtml: null
|
|
18
18
|
}
|
|
19
19
|
}]);
|
|
20
|
-
if (!Array.isArray(
|
|
21
|
-
const l =
|
|
22
|
-
return
|
|
23
|
-
type:
|
|
20
|
+
if (!Array.isArray(e.data)) {
|
|
21
|
+
const l = e.data;
|
|
22
|
+
return t({
|
|
23
|
+
type: r.Warning,
|
|
24
24
|
message: l.message ?? s("journey-builder.liquid-validation-failed")
|
|
25
25
|
}), !1;
|
|
26
26
|
}
|
|
27
|
-
const [
|
|
28
|
-
return n.length ? (
|
|
29
|
-
type:
|
|
27
|
+
const [a] = e.data, n = Object.values((a == null ? void 0 : a.errors) ?? {});
|
|
28
|
+
return n.length ? (t({
|
|
29
|
+
type: r.Warning,
|
|
30
30
|
message: n[0].replace(/^line \d+:\s*/, "")
|
|
31
31
|
}), !1) : !0;
|
|
32
|
-
} catch {
|
|
33
|
-
return e({
|
|
34
|
-
type:
|
|
32
|
+
} catch (e) {
|
|
33
|
+
return e != null && e.authReported || t({
|
|
34
|
+
type: r.Error,
|
|
35
35
|
message: s("journey-builder.liquid-validation-failed")
|
|
36
36
|
}), !1;
|
|
37
37
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ToasterTypeOptions as
|
|
1
|
+
import { ToasterTypeOptions as c } from "../../enums/toaster.js";
|
|
2
2
|
import { PAGE_TYPES as u } from "../../enums/unsubscribe.js";
|
|
3
|
-
import { UNSUBSCRIBE_BLOCK_SELECTOR as
|
|
4
|
-
import { useToaster as
|
|
5
|
-
import { useTranslations as
|
|
3
|
+
import { UNSUBSCRIBE_BLOCK_SELECTOR as i, DATA_ATTRIBUTES as a } from "../../extensions/Blocks/Unsubscribe/utils/constants.js";
|
|
4
|
+
import { useToaster as p } from "../useToaster.js";
|
|
5
|
+
import { useTranslations as l } from "../useTranslations.js";
|
|
6
6
|
const T = [
|
|
7
7
|
{
|
|
8
8
|
pageType: u.GLOBAL_UNSUBSCRIBE,
|
|
@@ -12,30 +12,37 @@ const T = [
|
|
|
12
12
|
pageType: u.SUBSCRIPTION_PREFERENCE_CENTER,
|
|
13
13
|
messageKey: "unsubscription-preference.duplicate-pref-center"
|
|
14
14
|
}
|
|
15
|
-
], g = "unsubscription-preference.duplicate-both",
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
15
|
+
], g = "unsubscription-preference.duplicate-both", E = "unsubscription-preference.select-page-to-continue";
|
|
16
|
+
function m(r) {
|
|
17
|
+
const s = new DOMParser().parseFromString(r, "text/html"), t = /* @__PURE__ */ new Map();
|
|
18
|
+
return s.querySelectorAll(i).forEach((n) => {
|
|
19
|
+
const e = Number(n.getAttribute(a.PAGE_TYPE));
|
|
20
|
+
t.set(e, (t.get(e) ?? 0) + 1);
|
|
21
|
+
}), T.filter((n) => (t.get(n.pageType) ?? 0) > 1);
|
|
22
|
+
}
|
|
23
|
+
function b(r) {
|
|
24
|
+
const s = new DOMParser().parseFromString(r, "text/html");
|
|
25
|
+
return Array.from(s.querySelectorAll(i)).filter((t) => {
|
|
26
|
+
const n = t.getAttribute(a.PAGE_TYPE), e = t.getAttribute(a.PAGE_LIST);
|
|
27
|
+
return !n || !e;
|
|
28
|
+
}).length;
|
|
29
|
+
}
|
|
30
|
+
const y = () => {
|
|
31
|
+
const { showToaster: r } = p(), s = l();
|
|
32
|
+
return { validateUnsubscribeBlockUniqueness: (e) => {
|
|
33
|
+
const o = m(e);
|
|
34
|
+
return o.length ? (r({
|
|
35
|
+
type: c.Error,
|
|
36
|
+
message: s(o.length > 1 ? g : o[0].messageKey)
|
|
27
37
|
}), !1) : !0;
|
|
28
|
-
}, validateUnsubscribeBlockHasTemplate: (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return !e || !s;
|
|
33
|
-
}) ? (c({
|
|
34
|
-
type: i.Warning,
|
|
35
|
-
message: p(b)
|
|
36
|
-
}), !1) : !0;
|
|
37
|
-
} };
|
|
38
|
+
}, validateUnsubscribeBlockHasTemplate: (e) => b(e) === 0 ? !0 : (r({
|
|
39
|
+
type: c.Warning,
|
|
40
|
+
message: s(E)
|
|
41
|
+
}), !1) };
|
|
38
42
|
};
|
|
39
43
|
export {
|
|
40
|
-
|
|
44
|
+
E as EMPTY_BLOCK_KEY,
|
|
45
|
+
b as countUnsubBlocksWithoutPage,
|
|
46
|
+
m as findDuplicateUnsubPageTypes,
|
|
47
|
+
y as useUnsubscribeBlockValidator
|
|
41
48
|
};
|