@useinsider/guido 1.0.3-beta.e0403cf → 1.0.3-beta.e32f324
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 +3 -0
- package/dist/components/Guido.vue.js +1 -1
- package/dist/components/Guido.vue2.js +79 -73
- package/dist/components/organisms/header/RightSlot.vue.js +1 -1
- package/dist/components/organisms/header/RightSlot.vue2.js +23 -22
- package/dist/composables/useGuidoActions.js +19 -9
- package/dist/composables/useStripo.js +37 -35
- package/dist/config/compiler/unsubscribeCompilerRules.js +33 -28
- package/dist/enums/defaults.js +2 -1
- package/dist/enums/unsubscribe.js +27 -25
- package/dist/extensions/Blocks/Checkbox/control.js +15 -14
- package/dist/extensions/Blocks/RadioButton/control.js +18 -17
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +1 -1
- package/dist/extensions/DynamicContent/dynamic-content-modal.js +25 -19
- package/dist/extensions/DynamicContent/dynamic-content.js +128 -33
- package/dist/guido.css +1 -1
- package/dist/src/@types/generic.d.ts +27 -6
- package/dist/src/components/Guido.vue.d.ts +3 -2
- package/dist/src/composables/useGuidoActions.d.ts +9 -0
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +1 -1
- package/dist/src/extensions/DynamicContent/dynamic-content-modal.d.ts +9 -2
- package/dist/src/extensions/DynamicContent/dynamic-content.d.ts +52 -2
- package/dist/src/stores/config.d.ts +3 -2
- package/dist/src/stores/dynamic-content.d.ts +3 -3
- package/dist/src/stores/editor.d.ts +1 -1
- package/dist/src/stores/onboarding.d.ts +1 -1
- package/dist/src/stores/preview.d.ts +1 -1
- package/dist/src/stores/recommendation.d.ts +1 -1
- package/dist/src/stores/save-as-template.d.ts +1 -1
- package/dist/src/stores/toaster.d.ts +1 -1
- package/dist/src/stores/unsubscribe.d.ts +1 -1
- package/dist/src/stores/version-history.d.ts +1 -1
- package/dist/src/utils/environmentUtil.d.ts +5 -0
- package/dist/src/utils/genericUtil.d.ts +1 -0
- package/dist/stores/config.js +5 -5
- package/dist/stores/dynamic-content.js +2 -2
- package/dist/stores/editor.js +1 -1
- package/dist/stores/onboarding.js +27 -27
- package/dist/stores/preview.js +1 -1
- package/dist/stores/recommendation.js +3 -3
- package/dist/stores/save-as-template.js +2 -2
- package/dist/stores/toaster.js +1 -1
- package/dist/stores/unsubscribe.js +1 -1
- package/dist/stores/version-history.js +4 -4
- package/dist/utils/environmentUtil.js +4 -0
- package/dist/utils/genericUtil.js +20 -9
- package/package.json +1 -1
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
import { useTranslations as
|
|
2
|
-
|
|
1
|
+
import { useTranslations as n } from "../composables/useTranslations.js";
|
|
2
|
+
import { getEnvironmentPrefix as R } from "../utils/environmentUtil.js";
|
|
3
|
+
const e = n(), I = {
|
|
3
4
|
UNSUBSCRIBE_LINK_TYPE: 1,
|
|
4
5
|
PREFERENCES_LINK_TYPE: 3
|
|
5
|
-
},
|
|
6
|
+
}, r = {
|
|
6
7
|
UNSUBSCRIBE_LINK_REGEX: /{{ins-unsubscribe-link}}/g,
|
|
7
8
|
DATA_OGSB_BUTTON_CSS_REGEX: "\\[data-ogsb\\]\\s*\\.es-button\\.es-button-[0-9]+\\s*\\{(?:[^\\}]*)\\}",
|
|
8
9
|
GLOBAL_UNSUBSCRIBE_LINK_REGEX: /{{ins-global-unsubscribe-link}}/g,
|
|
9
10
|
PREFERENCES_UNSUBSCRIBE_LINK_REGEX: /{{ins-preferences-unsubscribe-link}}/g
|
|
10
|
-
},
|
|
11
|
-
UNSUBSCRIBE_URL:
|
|
12
|
-
PREFERENCES_URL:
|
|
13
|
-
},
|
|
11
|
+
}, s = R(), _ = {
|
|
12
|
+
UNSUBSCRIBE_URL: `https://mail.${s}.com/user/v1/unsub`,
|
|
13
|
+
PREFERENCES_URL: `https://mail.${s}.com/user/v1/prefs`
|
|
14
|
+
}, i = "iid", B = {
|
|
14
15
|
name: "Global Unsubscribe",
|
|
15
16
|
sendGridId: "G"
|
|
16
|
-
},
|
|
17
|
+
}, C = "https://academy.useinsider.com/docs/global-unsubscribe-preference-center", c = "/email/unsubscribe-pages", E = {
|
|
17
18
|
GLOBAL_UNSUBSCRIBE: 1,
|
|
18
19
|
GLOBAL_UNSUBSCRIBE_CONFIRMATION_PAGE: 2,
|
|
19
20
|
SUBSCRIPTION_PREFERENCE_CENTER: 3,
|
|
20
21
|
SUBSCRIPTION_PREFERENCE_CONFIRMATION: 4,
|
|
21
22
|
RESUBSCRIBE: 5
|
|
22
|
-
},
|
|
23
|
+
}, t = {
|
|
23
24
|
[E.GLOBAL_UNSUBSCRIBE]: [
|
|
24
25
|
E.GLOBAL_UNSUBSCRIBE,
|
|
25
26
|
E.GLOBAL_UNSUBSCRIBE_CONFIRMATION_PAGE,
|
|
@@ -29,26 +30,27 @@ const s = e(), R = {
|
|
|
29
30
|
E.SUBSCRIPTION_PREFERENCE_CENTER,
|
|
30
31
|
E.SUBSCRIPTION_PREFERENCE_CONFIRMATION
|
|
31
32
|
]
|
|
32
|
-
},
|
|
33
|
-
[E.GLOBAL_UNSUBSCRIBE]:
|
|
34
|
-
[E.GLOBAL_UNSUBSCRIBE_CONFIRMATION_PAGE]:
|
|
35
|
-
[E.RESUBSCRIBE]:
|
|
36
|
-
[E.SUBSCRIPTION_PREFERENCE_CENTER]:
|
|
37
|
-
[E.SUBSCRIPTION_PREFERENCE_CONFIRMATION]:
|
|
38
|
-
},
|
|
33
|
+
}, U = {
|
|
34
|
+
[E.GLOBAL_UNSUBSCRIBE]: e("unsubscription-preference.type-global-unsubscribe"),
|
|
35
|
+
[E.GLOBAL_UNSUBSCRIBE_CONFIRMATION_PAGE]: e("unsubscription-preference.type-global-unsubscription-confirmation"),
|
|
36
|
+
[E.RESUBSCRIBE]: e("unsubscription-preference.type-resubscribe"),
|
|
37
|
+
[E.SUBSCRIPTION_PREFERENCE_CENTER]: e("unsubscription-preference.type-subscription-preferences-center"),
|
|
38
|
+
[E.SUBSCRIPTION_PREFERENCE_CONFIRMATION]: e("unsubscription-preference.type-subscription-preferences-confirmation")
|
|
39
|
+
}, o = {
|
|
39
40
|
default: "{{ins-unsubscribe-link}}",
|
|
40
41
|
[E.GLOBAL_UNSUBSCRIBE]: "{{ins-global-unsubscribe-link}}",
|
|
41
42
|
[E.SUBSCRIPTION_PREFERENCE_CENTER]: "{{ins-preferences-unsubscribe-link}}"
|
|
42
43
|
};
|
|
43
44
|
export {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
C as ACADEMY_LINK,
|
|
46
|
+
B as DEFAULT_UNSUBSCRIBE_GROUP,
|
|
47
|
+
i as INSIDER_ID,
|
|
48
|
+
r as LINK_REGEXES,
|
|
49
|
+
I as LINK_TYPES,
|
|
50
|
+
o as MERGE_TAGS,
|
|
49
51
|
E as PAGE_TYPES,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
t as TYPE_COLLECTIONS,
|
|
53
|
+
U as TYPE_TRANSLATIONS,
|
|
54
|
+
c as UNSUBSCRIBE_PAGES_LINK,
|
|
55
|
+
_ as URLS
|
|
54
56
|
};
|
|
@@ -2,9 +2,9 @@ var d = Object.defineProperty;
|
|
|
2
2
|
var l = (r, n, e) => n in r ? d(r, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[n] = e;
|
|
3
3
|
var o = (r, n, e) => l(r, typeof n != "symbol" ? n + "" : n, e);
|
|
4
4
|
import { useHttp as L } from "../../../composables/useHttp.js";
|
|
5
|
-
import { DEFAULT_UNSUBSCRIBE_GROUP as
|
|
5
|
+
import { DEFAULT_UNSUBSCRIBE_GROUP as c } from "../../../enums/unsubscribe.js";
|
|
6
6
|
import { Control as h, UIElementType as i, UEAttr as t, ModificationDescription as p } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
7
|
-
const m = "ui-elements-checkbox",
|
|
7
|
+
const m = "ui-elements-checkbox", u = "select", { get: C } = L();
|
|
8
8
|
class S extends h {
|
|
9
9
|
constructor() {
|
|
10
10
|
super(...arguments);
|
|
@@ -16,14 +16,15 @@ class S extends h {
|
|
|
16
16
|
return m;
|
|
17
17
|
}
|
|
18
18
|
_setFormValues() {
|
|
19
|
-
if (this.currentNode && "getAttribute" in this.currentNode) {
|
|
19
|
+
if (this.selectedUnsubGroup = "", this.currentNode && "getAttribute" in this.currentNode) {
|
|
20
20
|
const e = this.currentNode.getAttribute("id");
|
|
21
21
|
if (e) {
|
|
22
|
-
const s = e ===
|
|
23
|
-
s && (this.selectedUnsubGroup = s
|
|
24
|
-
[a]: this.selectedUnsubGroup
|
|
25
|
-
}));
|
|
22
|
+
const s = e === c.sendGridId ? e : Number(e);
|
|
23
|
+
s && (this.selectedUnsubGroup = s);
|
|
26
24
|
}
|
|
25
|
+
this.api.updateValues({
|
|
26
|
+
[u]: this.selectedUnsubGroup
|
|
27
|
+
});
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
_getLabel(e, s = `${Math.random()}`) {
|
|
@@ -54,7 +55,7 @@ class S extends h {
|
|
|
54
55
|
</${i.LABEL}>
|
|
55
56
|
|
|
56
57
|
<${i.SELECTPICKER}
|
|
57
|
-
${t.SELECTPICKER.name}="${
|
|
58
|
+
${t.SELECTPICKER.name}="${u}"
|
|
58
59
|
${t.SELECTPICKER.placeholder}="${this.api.translate("Select Unsubscribe Group")}">
|
|
59
60
|
${this._getSelect()}
|
|
60
61
|
</${i.SELECTPICKER}>
|
|
@@ -66,21 +67,21 @@ class S extends h {
|
|
|
66
67
|
this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute("id", e.toString()).apply(new p(`Updated text to ${e}`));
|
|
67
68
|
}
|
|
68
69
|
_listenToFormUpdates() {
|
|
69
|
-
this.api.onValueChanged(
|
|
70
|
+
this.api.onValueChanged(u, (e) => this._onSelectChange(e));
|
|
70
71
|
}
|
|
71
72
|
onTemplateNodeUpdated(e) {
|
|
72
|
-
this.currentNode = e;
|
|
73
|
+
this.currentNode = e, this._setFormValues();
|
|
73
74
|
}
|
|
74
75
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
75
76
|
async onRender() {
|
|
76
77
|
const e = await C(
|
|
77
78
|
"/unsubscribe-groups/unsubscribe-list"
|
|
78
|
-
), s = [
|
|
79
|
-
[t.SELECT_ITEM.text]:
|
|
80
|
-
[t.SELECT_ITEM.value]:
|
|
79
|
+
), s = [c, ...e.data], E = s.map((a) => ({
|
|
80
|
+
[t.SELECT_ITEM.text]: a.name,
|
|
81
|
+
[t.SELECT_ITEM.value]: a.sendGridId
|
|
81
82
|
}));
|
|
82
83
|
this.unsubList = s, this.api.setUIEAttribute(
|
|
83
|
-
|
|
84
|
+
u,
|
|
84
85
|
t.SELECTPICKER.items,
|
|
85
86
|
E
|
|
86
87
|
), this._setFormValues(), this._listenToFormUpdates();
|
|
@@ -2,10 +2,10 @@ var d = Object.defineProperty;
|
|
|
2
2
|
var l = (r, n, t) => n in r ? d(r, n, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[n] = t;
|
|
3
3
|
var o = (r, n, t) => l(r, typeof n != "symbol" ? n + "" : n, t);
|
|
4
4
|
import { useHttp as L } from "../../../composables/useHttp.js";
|
|
5
|
-
import { DEFAULT_UNSUBSCRIBE_GROUP as
|
|
5
|
+
import { DEFAULT_UNSUBSCRIBE_GROUP as c } from "../../../enums/unsubscribe.js";
|
|
6
6
|
import { Control as p, UIElementType as i, UEAttr as e, ModificationDescription as h } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
7
|
-
const m = "ui-elements-radio-button",
|
|
8
|
-
class
|
|
7
|
+
const m = "ui-elements-radio-button", u = "select", { get: $ } = L();
|
|
8
|
+
class S extends p {
|
|
9
9
|
constructor() {
|
|
10
10
|
super(...arguments);
|
|
11
11
|
o(this, "currentNode");
|
|
@@ -16,15 +16,16 @@ class _ extends p {
|
|
|
16
16
|
return m;
|
|
17
17
|
}
|
|
18
18
|
_setFormValues() {
|
|
19
|
-
if (this.currentNode && "getAttribute" in this.currentNode) {
|
|
19
|
+
if (this.selectedUnsubGroup = "", this.currentNode && "getAttribute" in this.currentNode) {
|
|
20
20
|
const t = this.currentNode.getAttribute("id");
|
|
21
21
|
if (t) {
|
|
22
|
-
const s = t ===
|
|
23
|
-
s && (this.selectedUnsubGroup = s
|
|
24
|
-
[a]: this.selectedUnsubGroup
|
|
25
|
-
}));
|
|
22
|
+
const s = t === c.sendGridId ? t : Number(t);
|
|
23
|
+
s && (this.selectedUnsubGroup = s);
|
|
26
24
|
}
|
|
27
25
|
}
|
|
26
|
+
this.api.updateValues({
|
|
27
|
+
[u]: this.selectedUnsubGroup
|
|
28
|
+
});
|
|
28
29
|
}
|
|
29
30
|
_getLabel(t, s = `${Math.random()}`) {
|
|
30
31
|
return `
|
|
@@ -54,7 +55,7 @@ class _ extends p {
|
|
|
54
55
|
</${i.LABEL}>
|
|
55
56
|
|
|
56
57
|
<${i.SELECTPICKER}
|
|
57
|
-
${e.SELECTPICKER.name}="${
|
|
58
|
+
${e.SELECTPICKER.name}="${u}"
|
|
58
59
|
${e.SELECTPICKER.placeholder}="${this.api.translate("Select Unsubscribe Group")}">
|
|
59
60
|
${this._getSelect()}
|
|
60
61
|
</${i.SELECTPICKER}>
|
|
@@ -66,27 +67,27 @@ class _ extends p {
|
|
|
66
67
|
this.currentNode && this.api.getDocumentModifier().modifyHtml(this.currentNode).setAttribute("id", t.toString()).apply(new h(`Updated text to ${t}`));
|
|
67
68
|
}
|
|
68
69
|
_listenToFormUpdates() {
|
|
69
|
-
this.api.onValueChanged(
|
|
70
|
+
this.api.onValueChanged(u, (t) => this._onSelectChange(t));
|
|
70
71
|
}
|
|
71
72
|
onTemplateNodeUpdated(t) {
|
|
72
|
-
this.currentNode = t;
|
|
73
|
+
this.currentNode = t, this._setFormValues();
|
|
73
74
|
}
|
|
74
75
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
75
76
|
async onRender() {
|
|
76
77
|
const t = await $(
|
|
77
78
|
"/unsubscribe-groups/unsubscribe-list"
|
|
78
|
-
), s = [
|
|
79
|
-
[e.SELECT_ITEM.text]:
|
|
80
|
-
[e.SELECT_ITEM.value]:
|
|
79
|
+
), s = [c, ...t.data], E = s.map((a) => ({
|
|
80
|
+
[e.SELECT_ITEM.text]: a.name,
|
|
81
|
+
[e.SELECT_ITEM.value]: a.sendGridId
|
|
81
82
|
}));
|
|
82
83
|
this.unsubList = s, this.api.setUIEAttribute(
|
|
83
|
-
|
|
84
|
+
u,
|
|
84
85
|
e.SELECTPICKER.items,
|
|
85
|
-
|
|
86
|
+
E
|
|
86
87
|
), this._setFormValues(), this._listenToFormUpdates();
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
90
|
export {
|
|
90
91
|
m as CONTROL_BLOCK_ID,
|
|
91
|
-
|
|
92
|
+
S as RadioButtonControl
|
|
92
93
|
};
|
|
@@ -133,7 +133,7 @@ const a = c(), d = () => ({
|
|
|
133
133
|
filterSelectionDrawerStatus: !1,
|
|
134
134
|
filterList: {},
|
|
135
135
|
filterGroup: 1
|
|
136
|
-
}), G = p("
|
|
136
|
+
}), G = p("guidoRecommendationExtension", {
|
|
137
137
|
state: () => d(),
|
|
138
138
|
getters: {
|
|
139
139
|
hasFilters: (e) => !!e.recommendationConfigs.filters.length,
|
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
class
|
|
1
|
+
var d = Object.defineProperty;
|
|
2
|
+
var m = (t, e, n) => e in t ? d(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n;
|
|
3
|
+
var c = (t, e, n) => m(t, typeof e != "symbol" ? e + "" : e, n);
|
|
4
|
+
class C {
|
|
5
5
|
constructor() {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
c(this, "selectedDynamicContent", null);
|
|
7
|
+
c(this, "dataSelectCallback", () => {
|
|
8
8
|
});
|
|
9
|
+
c(this, "closeDynamicContentHandler", null);
|
|
9
10
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Opens the merge tags library modal
|
|
13
|
+
* @param dynamicContent - Currently selected dynamic content (if any)
|
|
14
|
+
* @param onDataSelectCallback - Callback invoked when user selects a merge tag
|
|
15
|
+
* @param position - Optional position data to place the modal
|
|
16
|
+
*/
|
|
17
|
+
openMergeTagsLibrary(e, n, l) {
|
|
18
|
+
this.closeDynamicContentHandler && (document.removeEventListener("dynamic-content:close", this.closeDynamicContentHandler), this.closeDynamicContentHandler = null), this.dataSelectCallback = n, this.selectedDynamicContent = e;
|
|
19
|
+
const o = {
|
|
20
|
+
attribute: e,
|
|
21
|
+
position: l
|
|
22
|
+
}, s = new CustomEvent("dynamic-content:open", {
|
|
23
|
+
detail: o
|
|
16
24
|
});
|
|
17
|
-
document.dispatchEvent(s)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
};
|
|
22
|
-
document.addEventListener("dynamic-content:close", o);
|
|
25
|
+
document.dispatchEvent(s), this.closeDynamicContentHandler = (i) => {
|
|
26
|
+
const a = i.detail;
|
|
27
|
+
this.selectedDynamicContent = a, a.text && a.value && this.dataSelectCallback(a);
|
|
28
|
+
}, document.addEventListener("dynamic-content:close", this.closeDynamicContentHandler);
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
export {
|
|
26
|
-
|
|
32
|
+
C as ExternalMergeTagsLibrary
|
|
27
33
|
};
|
|
@@ -1,61 +1,156 @@
|
|
|
1
|
-
var
|
|
2
|
-
var g = (
|
|
3
|
-
var
|
|
4
|
-
import { dynamicContentToMergeTags as m } from "../../utils/genericUtil.js";
|
|
5
|
-
import { UIElement as
|
|
6
|
-
import { ExternalMergeTagsLibrary as
|
|
7
|
-
const
|
|
8
|
-
class p extends
|
|
9
|
-
registerUiElements(
|
|
10
|
-
|
|
1
|
+
var c = Object.defineProperty;
|
|
2
|
+
var g = (o, s, t) => s in o ? c(o, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[s] = t;
|
|
3
|
+
var r = (o, s, t) => g(o, typeof s != "symbol" ? s + "" : s, t);
|
|
4
|
+
import { mergeTagToDynamicContent as d, dynamicContentToMergeTags as m } from "../../utils/genericUtil.js";
|
|
5
|
+
import { UIElement as u, UIElementType as a, UEAttr as h, UIElementTagRegistry as T } from "../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
6
|
+
import { ExternalMergeTagsLibrary as y } from "./dynamic-content-modal.js";
|
|
7
|
+
const l = "external-dynamic-content-ui-element", C = "button-add-dynamic-content";
|
|
8
|
+
class p extends T {
|
|
9
|
+
registerUiElements(s) {
|
|
10
|
+
s[a.MERGETAGS] = l;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
class
|
|
13
|
+
class b extends u {
|
|
14
14
|
constructor() {
|
|
15
15
|
super(...arguments);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
r(this, "mergeTagsButton", null);
|
|
17
|
+
r(this, "mergeTagsLibrary", null);
|
|
18
|
+
r(this, "clickListener", null);
|
|
19
|
+
r(this, "lastClickedElement", null);
|
|
20
|
+
r(this, "lastClickedFrame", null);
|
|
21
|
+
r(this, "mousedownListener", null);
|
|
21
22
|
}
|
|
22
23
|
getId() {
|
|
23
|
-
return
|
|
24
|
+
return l;
|
|
24
25
|
}
|
|
25
|
-
onRender(
|
|
26
|
-
var
|
|
27
|
-
this.
|
|
26
|
+
onRender(t) {
|
|
27
|
+
var e;
|
|
28
|
+
this.mergeTagsButton = t.querySelector("#guido__btn-add-dynamic-content"), this.clickListener = this._onClick.bind(this), (e = this.mergeTagsButton) == null || e.addEventListener("click", this.clickListener), this._setupCoordinateTracking();
|
|
28
29
|
}
|
|
29
30
|
onDestroy() {
|
|
30
|
-
var
|
|
31
|
-
(
|
|
31
|
+
var t;
|
|
32
|
+
this.clickListener && ((t = this.mergeTagsButton) == null || t.removeEventListener("click", this.clickListener)), this._cleanupCoordinateTracking(), this.mergeTagsButton = null, this.clickListener = null, this.lastClickedElement = null, this.lastClickedFrame = null;
|
|
32
33
|
}
|
|
33
34
|
_onClick() {
|
|
34
35
|
this.openMergeTagLibrary();
|
|
35
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Called when Stripo detects merge tag interactions
|
|
39
|
+
* This is the key method that receives notifications about merge tag clicks
|
|
40
|
+
* @param name - Attribute name (e.g., 'mergeTag')
|
|
41
|
+
* @param value - MergeTag object with label, value, selStart, selEnd, etc.
|
|
42
|
+
*/
|
|
43
|
+
onAttributeUpdated(t, e) {
|
|
44
|
+
if (t !== "mergeTag" || !(e != null && e.value))
|
|
45
|
+
return;
|
|
46
|
+
const n = d(e), i = this._getLastClickedPosition();
|
|
47
|
+
this.lastClickedElement = null, this.lastClickedFrame = null, this._openDynamicContentLibrary(n, i);
|
|
48
|
+
}
|
|
36
49
|
openMergeTagLibrary() {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
50
|
+
const t = this._getButtonPosition(), e = { value: "", text: "" };
|
|
51
|
+
this._openDynamicContentLibrary(e, t);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Opens the dynamic content library for external apps
|
|
55
|
+
* Dispatches event with dynamic content data and position
|
|
56
|
+
*/
|
|
57
|
+
_openDynamicContentLibrary(t, e) {
|
|
58
|
+
this.mergeTagsLibrary || (this.mergeTagsLibrary = new y()), this.mergeTagsLibrary.openMergeTagsLibrary(
|
|
59
|
+
t,
|
|
60
|
+
(n) => {
|
|
61
|
+
n.text && n.value ? this.api.triggerValueChange(m([n])[0]) : this.api.triggerValueChange(null);
|
|
62
|
+
},
|
|
63
|
+
e
|
|
42
64
|
);
|
|
43
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Gets the button's position on the screen
|
|
68
|
+
* Used to position the modal or anything else near the button
|
|
69
|
+
*/
|
|
70
|
+
_getButtonPosition() {
|
|
71
|
+
if (!this.mergeTagsButton)
|
|
72
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
73
|
+
const { x: t, y: e, width: n, height: i } = this.mergeTagsButton.getBoundingClientRect();
|
|
74
|
+
return { x: t, y: e, width: n, height: i };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Sets up coordinate tracking for merge tag clicks in the iframe
|
|
78
|
+
* Workaround from Stripo intercepting click events - tracks mousedown events instead
|
|
79
|
+
*/
|
|
80
|
+
_setupCoordinateTracking() {
|
|
81
|
+
var e;
|
|
82
|
+
const t = this._getEditorFrame();
|
|
83
|
+
(e = t == null ? void 0 : t.contentWindow) != null && e.document && (this.mousedownListener = (n) => {
|
|
84
|
+
const i = this._findMergeTagElement(n.target);
|
|
85
|
+
i && (this.lastClickedElement = i, this.lastClickedFrame = t);
|
|
86
|
+
}, t.contentWindow.document.addEventListener("mousedown", this.mousedownListener));
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Gets the editor iframe element
|
|
90
|
+
*/
|
|
91
|
+
_getEditorFrame() {
|
|
92
|
+
var n;
|
|
93
|
+
const t = document.querySelector("ui-editor");
|
|
94
|
+
if (!(t != null && t.shadowRoot))
|
|
95
|
+
return null;
|
|
96
|
+
const e = t.shadowRoot.querySelector("iframe");
|
|
97
|
+
return (n = e == null ? void 0 : e.contentWindow) != null && n.document ? e : null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Finds merge tag element in the element tree
|
|
101
|
+
*/
|
|
102
|
+
_findMergeTagElement(t) {
|
|
103
|
+
return t.closest(".target, .esd-merge-tag");
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Gets the position of the last clicked element, calculated on-demand
|
|
107
|
+
* This ensures we always use the correct element's position even with rapid clicks
|
|
108
|
+
*/
|
|
109
|
+
_getLastClickedPosition() {
|
|
110
|
+
if (!(!this.lastClickedElement || !this.lastClickedFrame))
|
|
111
|
+
return this._calculateAbsolutePosition(this.lastClickedFrame, this.lastClickedElement);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Calculates absolute position of element relative to page
|
|
115
|
+
*/
|
|
116
|
+
_calculateAbsolutePosition(t, e) {
|
|
117
|
+
const n = t.getBoundingClientRect(), i = e.getBoundingClientRect();
|
|
118
|
+
return {
|
|
119
|
+
x: n.x + i.x,
|
|
120
|
+
y: n.y + i.y,
|
|
121
|
+
width: i.width,
|
|
122
|
+
height: i.height
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Cleans up the coordinate tracking event listener
|
|
127
|
+
*/
|
|
128
|
+
_cleanupCoordinateTracking() {
|
|
129
|
+
var e;
|
|
130
|
+
if (!this.mousedownListener)
|
|
131
|
+
return;
|
|
132
|
+
const t = this._getEditorFrame();
|
|
133
|
+
(e = t == null ? void 0 : t.contentWindow) != null && e.document && t.contentWindow.document.removeEventListener("mousedown", this.mousedownListener), this.mousedownListener = null;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Returns the HTML template for the "Add Dynamic Content" button
|
|
137
|
+
* This button is placed in the merge tags selector UI
|
|
138
|
+
*/
|
|
44
139
|
getTemplate() {
|
|
45
140
|
return `
|
|
46
141
|
<div>
|
|
47
|
-
<${
|
|
142
|
+
<${a.BUTTON}
|
|
48
143
|
id="guido__btn-add-dynamic-content"
|
|
49
144
|
class="btn btn-primary"
|
|
50
|
-
${
|
|
51
|
-
<${
|
|
52
|
-
</${
|
|
145
|
+
${h.BUTTON.name}="${C}">
|
|
146
|
+
<${a.ICON} src="plus" class="icon icon-button color-primary">
|
|
147
|
+
</${a.ICON}>
|
|
53
148
|
${this.api.translate("Add Dynamic Content")}
|
|
54
|
-
</${
|
|
149
|
+
</${a.BUTTON}>
|
|
55
150
|
</div>`;
|
|
56
151
|
}
|
|
57
152
|
}
|
|
58
153
|
export {
|
|
59
154
|
p as DynamicContentTagRegistry,
|
|
60
|
-
|
|
155
|
+
b as DynamicContentUiElementExtension
|
|
61
156
|
};
|
package/dist/guido.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.gap-16[data-v-6562e38c],.gap-16[data-v-1ccb6d4a]{gap:16px}[data-v-0502bceb] .in-button-v2__wrapper{line-height:0}[data-v-b5997368] .in-segments-wrapper .in-tooltip-wrapper__box{text-align:left}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history-wrapper[data-v-52a77eec]{gap:8px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.guido-loading__wrapper[data-v-dced5582]{height:100%;top:75px}.guido-editor__wrapper[data-v-
|
|
1
|
+
.gap-16[data-v-6562e38c],.gap-16[data-v-1ccb6d4a]{gap:16px}[data-v-0502bceb] .in-button-v2__wrapper{line-height:0}[data-v-b5997368] .in-segments-wrapper .in-tooltip-wrapper__box{text-align:left}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history-wrapper[data-v-52a77eec]{gap:8px}.view-options-wrapper[data-v-d405ca59]{position:relative;display:inline-block}.new-tag[data-v-d405ca59]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-d405ca59] .guido__verion-history-view-option-selection-desktop svg,[data-v-d405ca59] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-d405ca59] .in-segments-wrapper__button_selected,[data-v-d405ca59] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-d405ca59] .in-tooltip-wrapper__icon{cursor:pointer}.view-options-wrapper[data-v-195ab6d4]{position:relative;display:inline-block}.new-tag[data-v-195ab6d4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-195ab6d4] .guido__view-option-selection-desktop svg,[data-v-195ab6d4] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-195ab6d4] .in-segments-wrapper__button_selected,[data-v-195ab6d4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-195ab6d4] .in-tooltip-wrapper__icon{cursor:pointer}.guido-loading__wrapper[data-v-dced5582]{height:100%;top:75px}.guido-editor__wrapper[data-v-23c413c9],.guido-editor__container[data-v-23c413c9]{width:100%;height:calc(100vh - 128px)}.guido-editor__no-header[data-v-23c413c9]{height:calc(100vh - 75px)}[data-v-70835920] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-a86fc486]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-a86fc486]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-a86fc486]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-a86fc486]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-a86fc486]{object-fit:cover;transform:scale(1)}[data-v-dd57102d] .guido__verion-history-view-option-selection-desktop svg,[data-v-dd57102d] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-dd57102d] .in-segments-wrapper__button_selected,[data-v-dd57102d] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-7a09985c]{gap:16px}[data-v-c2adc57d] .in-progress-wrapper__progress p span:last-child{display:none!important}.desktop-preview-container[data-v-2dd60b0c],[data-v-2dd60b0c] .desktop-preview-container .in-container{min-height:720px!important;height:100%}.cropped-text[data-v-f20b3a9b]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}[data-v-d3c52b44] .vueperslides__bullets,[data-v-a408dcea] .vueperslides__bullets{pointer-events:none!important}[data-v-a408dcea] .vueperslides__parallax-wrapper{height:110px!important}
|
|
@@ -7,6 +7,7 @@ type Features = {
|
|
|
7
7
|
saveAsTemplate?: boolean;
|
|
8
8
|
versionHistory?: boolean;
|
|
9
9
|
testMessage?: boolean;
|
|
10
|
+
displayConditions?: boolean;
|
|
10
11
|
};
|
|
11
12
|
type Partner = {
|
|
12
13
|
partnerName: string;
|
|
@@ -37,15 +38,39 @@ export type TemplateConfig = {
|
|
|
37
38
|
selectedUnsubscribePages?: number[];
|
|
38
39
|
variationId?: string;
|
|
39
40
|
};
|
|
40
|
-
export type
|
|
41
|
+
export type BaseDynamicContent = {
|
|
41
42
|
value: string;
|
|
42
|
-
text: string;
|
|
43
43
|
fallback?: string;
|
|
44
44
|
format?: {
|
|
45
45
|
key: string;
|
|
46
46
|
value: string;
|
|
47
47
|
};
|
|
48
48
|
};
|
|
49
|
+
export type DynamicContent = BaseDynamicContent & {
|
|
50
|
+
text: string;
|
|
51
|
+
};
|
|
52
|
+
export type MergeTag = BaseDynamicContent & {
|
|
53
|
+
label: string;
|
|
54
|
+
selStart?: number;
|
|
55
|
+
selEnd?: number;
|
|
56
|
+
hidden?: boolean;
|
|
57
|
+
};
|
|
58
|
+
export type PositionData = {
|
|
59
|
+
x: number;
|
|
60
|
+
y: number;
|
|
61
|
+
width?: number;
|
|
62
|
+
height?: number;
|
|
63
|
+
};
|
|
64
|
+
export type DynamicContentEvent = {
|
|
65
|
+
attribute: DynamicContent;
|
|
66
|
+
position?: PositionData;
|
|
67
|
+
};
|
|
68
|
+
export type MergeTagClickEvent = {
|
|
69
|
+
position: PositionData;
|
|
70
|
+
element: HTMLElement;
|
|
71
|
+
tagValue: string | null;
|
|
72
|
+
tagLabel: string | null;
|
|
73
|
+
};
|
|
49
74
|
export interface EmailHeader {
|
|
50
75
|
senderName: string;
|
|
51
76
|
subject: string;
|
|
@@ -61,10 +86,6 @@ export interface TooltipOptions {
|
|
|
61
86
|
};
|
|
62
87
|
preventXss?: boolean;
|
|
63
88
|
}
|
|
64
|
-
export type MergeTag = {
|
|
65
|
-
label: string;
|
|
66
|
-
value: string;
|
|
67
|
-
};
|
|
68
89
|
export type TextValueObject = {
|
|
69
90
|
text: string;
|
|
70
91
|
value: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DynamicContent, GuidoConfig, TemplateConfig } from '@@/Types/generic';
|
|
1
|
+
import type { DynamicContent, GuidoConfig, PositionData, TemplateConfig } from '@@/Types/generic';
|
|
2
2
|
import type { SavedTemplateDetails } from '@@/Types/stripo';
|
|
3
3
|
type __VLS_Props = {
|
|
4
4
|
templateId: string;
|
|
@@ -20,13 +20,14 @@ declare const _default: import("vue").DefineComponent<__VLS_TypePropsToOption<__
|
|
|
20
20
|
hasChanges: import("vue").ComputedRef<boolean>;
|
|
21
21
|
saveSilent: () => Promise<SavedTemplateDetails | undefined> | undefined;
|
|
22
22
|
}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {
|
|
23
|
-
"dynamic-content:open": (detail: DynamicContent | null) => void;
|
|
23
|
+
"dynamic-content:open": (detail: DynamicContent | null, position?: PositionData | undefined) => void;
|
|
24
24
|
back: () => void;
|
|
25
25
|
"save:start": () => void;
|
|
26
26
|
"save:complete": (data: Omit<SavedTemplateDetails, "forceRecreate">) => void;
|
|
27
27
|
"on-change": (hasChanges: boolean) => void;
|
|
28
28
|
ready: () => void;
|
|
29
29
|
"onboarding:finished": () => void;
|
|
30
|
+
"test-email:click": () => void;
|
|
30
31
|
}, string, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<__VLS_Props>>>, {}>;
|
|
31
32
|
export default _default;
|
|
32
33
|
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
|
@@ -3,9 +3,11 @@ import type { InjectionKey } from 'vue';
|
|
|
3
3
|
export type BackHandler = () => void;
|
|
4
4
|
export type SaveStartHandler = () => void;
|
|
5
5
|
export type SaveCompleteHandler = (template: Omit<SavedTemplateDetails, 'forceRecreate'>) => void;
|
|
6
|
+
export type TestEmailClickHandler = () => void;
|
|
6
7
|
export declare const BACK_KEY: InjectionKey<BackHandler>;
|
|
7
8
|
export declare const SAVE_START_KEY: InjectionKey<SaveStartHandler>;
|
|
8
9
|
export declare const SAVE_COMPLETE_KEY: InjectionKey<SaveCompleteHandler>;
|
|
10
|
+
export declare const TEST_EMAIL_CLICK_KEY: InjectionKey<TestEmailClickHandler>;
|
|
9
11
|
/**
|
|
10
12
|
* Provides Guido action handlers to child components
|
|
11
13
|
*/
|
|
@@ -13,6 +15,7 @@ export declare const provideGuidoActions: (actions: {
|
|
|
13
15
|
onBack: BackHandler;
|
|
14
16
|
onSaveStart: SaveStartHandler;
|
|
15
17
|
onSaveComplete: SaveCompleteHandler;
|
|
18
|
+
onTestEmailClick: TestEmailClickHandler;
|
|
16
19
|
}) => void;
|
|
17
20
|
/**
|
|
18
21
|
* Provides individual Guido action handlers
|
|
@@ -35,6 +38,11 @@ export declare const useSaveStart: () => SaveStartHandler;
|
|
|
35
38
|
* @returns Save complete function
|
|
36
39
|
*/
|
|
37
40
|
export declare const useSaveComplete: () => SaveCompleteHandler;
|
|
41
|
+
/**
|
|
42
|
+
* Hook to use the test email click handler
|
|
43
|
+
* @returns Test email click function
|
|
44
|
+
*/
|
|
45
|
+
export declare const useTestEmailClick: () => TestEmailClickHandler;
|
|
38
46
|
/**
|
|
39
47
|
* Convenience hook to get all Guido actions
|
|
40
48
|
* @returns Object containing all action handlers
|
|
@@ -43,4 +51,5 @@ export declare const useGuidoActions: () => {
|
|
|
43
51
|
back: BackHandler;
|
|
44
52
|
saveStart: SaveStartHandler;
|
|
45
53
|
saveComplete: SaveCompleteHandler;
|
|
54
|
+
testEmailClick: TestEmailClickHandler;
|
|
46
55
|
};
|
|
@@ -34,7 +34,7 @@ interface StoreState {
|
|
|
34
34
|
filterList: FiltersResponse;
|
|
35
35
|
filterGroup: number;
|
|
36
36
|
}
|
|
37
|
-
export declare const useRecommendationExtensionStore: import("pinia").StoreDefinition<"
|
|
37
|
+
export declare const useRecommendationExtensionStore: import("pinia").StoreDefinition<"guidoRecommendationExtension", StoreState, {
|
|
38
38
|
hasFilters: (state: {
|
|
39
39
|
recommendationCampaignUrls: Record<string, string>;
|
|
40
40
|
recommendationConfigs: {
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import type { DynamicContent } from '@@/Types/generic';
|
|
1
|
+
import type { DynamicContent, PositionData } from '@@/Types/generic';
|
|
2
2
|
export declare class ExternalMergeTagsLibrary {
|
|
3
3
|
selectedDynamicContent: DynamicContent | null;
|
|
4
4
|
dataSelectCallback: (data: DynamicContent) => void;
|
|
5
|
-
|
|
5
|
+
private closeDynamicContentHandler;
|
|
6
|
+
/**
|
|
7
|
+
* Opens the merge tags library modal
|
|
8
|
+
* @param dynamicContent - Currently selected dynamic content (if any)
|
|
9
|
+
* @param onDataSelectCallback - Callback invoked when user selects a merge tag
|
|
10
|
+
* @param position - Optional position data to place the modal
|
|
11
|
+
*/
|
|
12
|
+
openMergeTagsLibrary(dynamicContent: DynamicContent, onDataSelectCallback: (data: DynamicContent) => void, position?: PositionData): void;
|
|
6
13
|
}
|