@useinsider/guido 3.17.0-beta.6255bfc → 3.17.0-beta.6b5cdfc
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 +5 -6
- package/dist/@types/config/schemas.js +6 -12
- package/dist/components/Guido.vue.js +2 -2
- package/dist/components/Guido.vue2.js +30 -31
- package/dist/composables/useCustomInterfaceAppearance.js +38 -52
- package/dist/composables/useRecommendation.js +44 -52
- package/dist/config/migrator/recommendation/settingsMapper.js +17 -19
- package/dist/config/migrator/recommendationMigrator.js +4 -6
- package/dist/enums/academy.js +1 -2
- package/dist/enums/date.js +3 -4
- package/dist/enums/extensions/recommendationBlock.js +1 -4
- package/dist/extensions/Blocks/Recommendation/block.js +21 -26
- package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +34 -36
- package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +95 -96
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +166 -180
- package/dist/extensions/Blocks/Recommendation/services/configService.js +35 -35
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +110 -251
- package/dist/extensions/Blocks/common-control.js +19 -22
- package/dist/guido.css +1 -1
- package/dist/services/recommendationApi.js +30 -75
- package/dist/src/@types/config/schemas.d.ts +0 -12
- package/dist/src/components/wrappers/WpModal.vue.d.ts +1 -1
- package/dist/src/composables/useConfig.d.ts +0 -2
- package/dist/src/composables/useRecommendation.d.ts +0 -1
- package/dist/src/enums/academy.d.ts +0 -1
- package/dist/src/enums/extensions/recommendationBlock.d.ts +0 -2
- package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +6 -7
- package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
- package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +3 -15
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +10 -206
- package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +0 -6
- package/dist/src/extensions/Blocks/common-control.d.ts +1 -4
- package/dist/src/services/recommendationApi.d.ts +1 -4
- package/dist/src/stores/config.d.ts +0 -18
- package/dist/src/utils/liquidDynamicContent.d.ts +18 -0
- package/dist/utils/dateUtil.js +10 -29
- package/dist/utils/genericUtil.js +54 -54
- package/dist/utils/liquidDynamicContent.js +14 -0
- package/dist/utils/templatePreparation.js +34 -37
- package/package.json +2 -3
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +0 -18
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +0 -66
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +0 -142
- package/dist/src/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.d.ts +0 -3
- package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +0 -30
- package/dist/src/mock/api/recommendation-strategies.d.ts +0 -63
- package/dist/src/utils/strategyInfoBox.d.ts +0 -22
- package/dist/static/assets/icons/line-change.svg.js +0 -5
- package/dist/static/assets/icons/line-delete.svg.js +0 -5
- package/dist/static/assets/icons/line-plus.svg.js +0 -5
- package/dist/static/styles/components/recommendation-strategy.css.js +0 -188
- package/dist/utils/strategyInfoBox.js +0 -37
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { formatToLiquidFilter as v, liquidFilterToFormat as b } from "./liquidDynamicContent.js";
|
|
2
|
+
const h = (t) => {
|
|
3
|
+
if (!t.includes("="))
|
|
4
|
+
return null;
|
|
5
|
+
const [e, a] = t.split("=");
|
|
6
|
+
return { key: e.trim(), value: a.trim() };
|
|
7
|
+
}, u = "default:", f = (t) => {
|
|
8
|
+
if (!t.startsWith(u))
|
|
9
|
+
return t;
|
|
10
|
+
const e = t.slice(u.length).trim();
|
|
11
|
+
return e.startsWith('"') && e.endsWith('"') ? e.slice(1, -1) : e;
|
|
12
|
+
}, g = (t) => {
|
|
13
|
+
const a = t.value.match(/\{\{([^}]+)\}\}/)[1].split("|").map((l) => l.trim()), [s] = a, n = {
|
|
14
|
+
text: t.label,
|
|
15
|
+
value: s || ""
|
|
5
16
|
};
|
|
6
17
|
if (a.length >= 2) {
|
|
7
|
-
const [,
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
n ? r.format = n : e || (r.fallback = t), e && (r.fallback = e);
|
|
18
|
+
const [, l, r] = a;
|
|
19
|
+
if (l.startsWith(u))
|
|
20
|
+
n.fallback = f(l);
|
|
21
|
+
else {
|
|
22
|
+
const c = b(l) ?? h(l);
|
|
23
|
+
c ? n.format = c : r || (n.fallback = l), r && (n.fallback = f(r));
|
|
14
24
|
}
|
|
15
25
|
}
|
|
16
|
-
return
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
label: `${a.text} | ${a.format.key}=${a.format.value}`,
|
|
21
|
-
value: `{{${a.value}|${a.format.key}=${a.format.value}}}`
|
|
22
|
-
};
|
|
23
|
-
if (s) {
|
|
24
|
-
if (!a.fallback)
|
|
25
|
-
return {
|
|
26
|
-
label: a.text,
|
|
27
|
-
value: `{{ ${a.value} }}`
|
|
28
|
-
};
|
|
29
|
-
const r = !Number.isNaN(Number(a.fallback)) && a.fallback.trim() !== "" ? a.fallback : `"${a.fallback}"`;
|
|
30
|
-
return {
|
|
31
|
-
label: `${a.text} | ${a.fallback}`,
|
|
32
|
-
value: `{{ ${a.value} | default: ${r} }}`
|
|
33
|
-
};
|
|
34
|
-
}
|
|
26
|
+
return n;
|
|
27
|
+
}, k = (t) => !Number.isNaN(Number(t)) && t.trim() !== "" ? t : `"${t}"`, m = (t) => {
|
|
28
|
+
const e = t.format ? v(t.format) : null, a = t.fallback ? `${u} ${k(t.fallback)}` : null, s = [t.value, e, a].filter(Boolean);
|
|
35
29
|
return {
|
|
36
|
-
label:
|
|
37
|
-
value:
|
|
30
|
+
label: [t.text, e, t.fallback || null].filter(Boolean).join(" | "),
|
|
31
|
+
value: `{{ ${s.join(" | ")} }}`
|
|
38
32
|
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
33
|
+
}, i = (t, e = !1) => t.map((a) => e ? m(a) : a.format ? {
|
|
34
|
+
label: `${a.text} | ${a.format.key}=${a.format.value}`,
|
|
35
|
+
value: `{{${a.value}|${a.format.key}=${a.format.value}}}`
|
|
36
|
+
} : {
|
|
37
|
+
label: a.fallback ? `${a.text} | ${a.fallback}` : a.text,
|
|
38
|
+
value: a.fallback ? `{{${a.value}|${a.fallback}}}` : `{{${a.value}}}`
|
|
39
|
+
}), d = (t) => {
|
|
40
|
+
const e = [], a = /* @__PURE__ */ new Set(), s = (l) => {
|
|
41
|
+
Array.isArray(l) && l.forEach((r) => {
|
|
42
|
+
const c = [...r.children ?? [], ...r.select_items ?? []];
|
|
43
|
+
if (c.length > 0) {
|
|
44
|
+
s(c);
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
-
const
|
|
48
|
-
|
|
47
|
+
const o = r.text || r.tag_text;
|
|
48
|
+
o && r.value && !a.has(r.value) && (a.add(r.value), e.push({ text: o, value: r.value }));
|
|
49
49
|
});
|
|
50
|
-
}, [
|
|
51
|
-
return
|
|
52
|
-
},
|
|
53
|
-
const
|
|
50
|
+
}, [n] = Object.values(t ?? {});
|
|
51
|
+
return s(n), e;
|
|
52
|
+
}, y = (t, e, a = !1) => {
|
|
53
|
+
const s = new Set(t.map((l) => l.value)), n = e.filter((l) => s.has(l.value) ? !1 : (s.add(l.value), !0));
|
|
54
54
|
return [
|
|
55
|
-
...
|
|
56
|
-
...
|
|
55
|
+
...i(t, a),
|
|
56
|
+
...i(n, a)
|
|
57
57
|
];
|
|
58
|
-
},
|
|
59
|
-
var
|
|
60
|
-
return ((
|
|
58
|
+
}, p = () => {
|
|
59
|
+
var t;
|
|
60
|
+
return ((t = document.head.querySelector('meta[name="csrf-token"]')) == null ? void 0 : t.getAttribute("content")) ?? "";
|
|
61
61
|
};
|
|
62
62
|
export {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
y as buildMergeTagEntries,
|
|
64
|
+
i as dynamicContentToMergeTags,
|
|
65
|
+
d as flattenDynamicContentList,
|
|
66
|
+
p as getCsrfToken,
|
|
67
|
+
g as mergeTagToDynamicContent
|
|
68
68
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const u = "time-format", r = "date", l = new RegExp(`^${r}\\s*:\\s*(?:"([^"]*)"|'([^']*)')$`), s = /%[-_0^#]?\d*[a-zA-Z%]/, E = (t) => t.includes('"') ? t.includes("'") ? null : `'${t}'` : `"${t}"`, c = (t) => {
|
|
2
|
+
if (t.key !== u || !s.test(t.value ?? ""))
|
|
3
|
+
return null;
|
|
4
|
+
const n = E(t.value);
|
|
5
|
+
return n === null ? null : `${r}: ${n}`;
|
|
6
|
+
}, i = (t) => {
|
|
7
|
+
const [, n, o] = t.match(l) ?? [], e = n ?? o;
|
|
8
|
+
return e ? { key: u, value: e } : null;
|
|
9
|
+
};
|
|
10
|
+
export {
|
|
11
|
+
u as TIME_FORMAT_KEY,
|
|
12
|
+
c as formatToLiquidFilter,
|
|
13
|
+
i as liquidFilterToFormat
|
|
14
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useActionsApi as k } from "../composables/useActionsApi.js";
|
|
2
2
|
import { useConfig as U } from "../composables/useConfig.js";
|
|
3
3
|
import { useHtmlCompiler as x } from "../composables/useHtmlCompiler.js";
|
|
4
|
-
import { DEFAULT_CURRENCY as d, DEFAULT_NODE_CONFIG as
|
|
4
|
+
import { DEFAULT_CURRENCY as d, DEFAULT_NODE_CONFIG as s } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
|
|
5
5
|
import { useRecommendationExtensionStore as C } from "../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
6
6
|
import { mapLegacyStrategy as L } from "../extensions/Blocks/Recommendation/utils/legacyStrategyMap.js";
|
|
7
7
|
import { DATA_ATTRIBUTES as A } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
|
|
@@ -11,20 +11,20 @@ import { useEditorStore as z } from "../stores/editor.js";
|
|
|
11
11
|
import { useUnsubscribeStore as _ } from "../stores/unsubscribe.js";
|
|
12
12
|
import { assignTrackingIds as v } from "./linkTrackingIds.js";
|
|
13
13
|
function O(m) {
|
|
14
|
-
const
|
|
15
|
-
return
|
|
16
|
-
const o =
|
|
14
|
+
const n = new DOMParser().parseFromString(m, "text/html").querySelectorAll(`[${A.PAGE_LIST}]`), t = [];
|
|
15
|
+
return n.forEach((i) => {
|
|
16
|
+
const o = i.getAttribute(A.PAGE_LIST);
|
|
17
17
|
o && t.push(...R(o));
|
|
18
18
|
}), [...new Set(t)];
|
|
19
19
|
}
|
|
20
20
|
async function M(m) {
|
|
21
|
-
const
|
|
22
|
-
if (
|
|
21
|
+
const a = new DOMParser().parseFromString(m, "text/html").querySelectorAll(".recommendation-block-v2");
|
|
22
|
+
if (a.length === 0)
|
|
23
23
|
return;
|
|
24
|
-
const
|
|
25
|
-
|
|
24
|
+
const n = C();
|
|
25
|
+
a.forEach((t) => {
|
|
26
26
|
var r, l, g, f, c;
|
|
27
|
-
const
|
|
27
|
+
const i = t.getAttribute("recommendation-id"), o = i ? Number(i) : NaN;
|
|
28
28
|
if (!Number.isFinite(o))
|
|
29
29
|
return;
|
|
30
30
|
const p = t.getAttribute("esd-ext-config");
|
|
@@ -42,27 +42,24 @@ async function M(m) {
|
|
|
42
42
|
// Normalize legacy strategy keys (e.g. `mostViewed` → `mostPopular`) so
|
|
43
43
|
// already-saved blocks that never re-run the migrator don't emit a
|
|
44
44
|
// strategy-less campaign URL. `||` also catches '' / undefined (SD-144882).
|
|
45
|
-
strategy: L(e.strategy) ||
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
strategyId: e.strategyId ?? a.strategyId,
|
|
49
|
-
language: e.language ?? a.language,
|
|
50
|
-
size: e.size ?? a.size,
|
|
45
|
+
strategy: L(e.strategy) || s.strategy,
|
|
46
|
+
language: e.language ?? s.language,
|
|
47
|
+
size: e.size ?? s.size,
|
|
51
48
|
// Spread the default arrays so each block gets a fresh reference
|
|
52
49
|
// instead of sharing the singleton in DEFAULT_NODE_CONFIG.
|
|
53
|
-
productIds: e.productIds ?? [...
|
|
54
|
-
filters: e.filters ?? [...
|
|
55
|
-
shuffleProducts: e.shuffleProducts ??
|
|
50
|
+
productIds: e.productIds ?? [...s.productIds],
|
|
51
|
+
filters: e.filters ?? [...s.filters],
|
|
52
|
+
shuffleProducts: e.shuffleProducts ?? s.shuffleProducts,
|
|
56
53
|
currencyCode: ((r = e.currency) == null ? void 0 : r.code) ?? d.code,
|
|
57
54
|
currencyAlignment: ((l = e.currency) == null ? void 0 : l.alignment) ?? d.alignment,
|
|
58
55
|
currencyDecimalCount: ((g = e.currency) == null ? void 0 : g.decimalCount) ?? d.decimalCount,
|
|
59
56
|
currencyDecimalSeparator: ((f = e.currency) == null ? void 0 : f.decimalSeparator) ?? d.decimalSeparator,
|
|
60
57
|
currencyThousandSeparator: ((c = e.currency) == null ? void 0 : c.thousandSeparator) ?? d.thousandSeparator
|
|
61
58
|
};
|
|
62
|
-
|
|
59
|
+
n.seedBlockUrlConfig(o, h);
|
|
63
60
|
});
|
|
64
61
|
try {
|
|
65
|
-
await
|
|
62
|
+
await n.fetchRecommendationCreateData();
|
|
66
63
|
} catch (t) {
|
|
67
64
|
console.warn(
|
|
68
65
|
"Recommendation reference data pre-load failed; validator will skip the availability check.",
|
|
@@ -71,39 +68,39 @@ async function M(m) {
|
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
70
|
const Z = () => {
|
|
74
|
-
const m = N(), u = z(),
|
|
71
|
+
const m = N(), u = z(), a = _(), { getCompiledEmail: n, getTemplateData: t, updateHtmlAndCss: i } = k(), { compileHtml: o, compileAmpHtml: p } = x(), { isFeatureEnabled: e } = U();
|
|
75
72
|
return {
|
|
76
73
|
prepareTemplateDetails: async () => {
|
|
77
74
|
let { html: r, css: l, syncModulesIds: g = [] } = await t();
|
|
78
75
|
if (e("linkTrackingIds"))
|
|
79
76
|
try {
|
|
80
|
-
const { html:
|
|
81
|
-
u.trackIdSessionFloor =
|
|
82
|
-
} catch (
|
|
83
|
-
console.error("Tracking-id step failed, saving anyway:",
|
|
77
|
+
const { html: y, changed: H, nextSeq: I } = v(r, u.trackIdSessionFloor);
|
|
78
|
+
u.trackIdSessionFloor = I, H && (r = y, await i(y, l));
|
|
79
|
+
} catch (y) {
|
|
80
|
+
console.error("Tracking-id step failed, saving anyway:", y);
|
|
84
81
|
}
|
|
85
|
-
const { html: f, ampHtml: c = "", ampErrors: T = [] } = await
|
|
82
|
+
const { html: f, ampHtml: c = "", ampErrors: T = [] } = await n({
|
|
86
83
|
minimize: !0,
|
|
87
84
|
resetDataSavedFlag: !1
|
|
88
85
|
});
|
|
89
|
-
|
|
90
|
-
const { compiledHtml:
|
|
86
|
+
a.selectedUnsubscribePages.length && await a.fetchTemplates(), await M(r);
|
|
87
|
+
const { compiledHtml: w, stats: S, appliedRules: D } = o(f), E = c && p(c).compiledHtml, P = m.getSelectedDynamicContentList, F = C(), b = O(r);
|
|
91
88
|
return console.debug("HTML Compilation Stats:", {
|
|
92
|
-
originalSize:
|
|
93
|
-
compiledSize:
|
|
94
|
-
reduction: `${
|
|
95
|
-
appliedRules:
|
|
96
|
-
executionTime: `${
|
|
89
|
+
originalSize: S.originalSize,
|
|
90
|
+
compiledSize: S.compiledSize,
|
|
91
|
+
reduction: `${S.reductionPercentage.toFixed(2)}%`,
|
|
92
|
+
appliedRules: D,
|
|
93
|
+
executionTime: `${S.executionTime.toFixed(2)}ms`
|
|
97
94
|
}), {
|
|
98
|
-
dynamicContentList:
|
|
99
|
-
compiledHtml:
|
|
95
|
+
dynamicContentList: P,
|
|
96
|
+
compiledHtml: w,
|
|
100
97
|
rawHtml: r,
|
|
101
98
|
css: l,
|
|
102
|
-
ampHtml:
|
|
99
|
+
ampHtml: E,
|
|
103
100
|
ampErrors: T,
|
|
104
101
|
modules: g.map(Number),
|
|
105
102
|
recommendation: {
|
|
106
|
-
campaignUrls:
|
|
103
|
+
campaignUrls: F.recommendationCampaignUrls,
|
|
107
104
|
configs: {}
|
|
108
105
|
},
|
|
109
106
|
unsubscribe: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinsider/guido",
|
|
3
|
-
"version": "3.17.0-beta.
|
|
3
|
+
"version": "3.17.0-beta.6b5cdfc",
|
|
4
4
|
"description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
|
|
5
5
|
"main": "./dist/guido.umd.cjs",
|
|
6
6
|
"module": "./dist/library.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"start": "vite",
|
|
26
26
|
"build": "vite build && vue-tsc --declaration --emitDeclarationOnly --project tsconfig.app.json",
|
|
27
27
|
"preview": "vite preview",
|
|
28
|
-
"lint": "NODE_OPTIONS=--max-old-space-size=2048 eslint ./ &&
|
|
28
|
+
"lint": "NODE_OPTIONS=--max-old-space-size=2048 eslint ./ && npm run type-check",
|
|
29
29
|
"lint:fix": "NODE_OPTIONS=--max-old-space-size=2048 eslint --fix ./",
|
|
30
30
|
"lint:e2e-quality": "node scripts/lint-e2e-quality.mjs",
|
|
31
31
|
"lint:e2e-quality:ci": "node scripts/lint-e2e-quality.mjs --ci",
|
|
@@ -48,7 +48,6 @@
|
|
|
48
48
|
"license": "ISC",
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@stripoinc/ui-editor-extensions": "3.9.0",
|
|
51
|
-
"@useinsider/design-system-organisms": "0.0.3-beta.fc2c160",
|
|
52
51
|
"@useinsider/design-system-vue": "1.5.0",
|
|
53
52
|
"@vueuse/core": "11.3.0",
|
|
54
53
|
"lodash-es": "4.17.21",
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import a from "./AssignStrategyDrawer.vue2.js";
|
|
2
|
-
/* empty css */
|
|
3
|
-
import r from "../../../../_virtual/_plugin-vue2_normalizer.js";
|
|
4
|
-
var o = function() {
|
|
5
|
-
var s = this, e = s._self._c, t = s._self._setupProxy;
|
|
6
|
-
return e(t.WpDrawer, { attrs: { id: "assign-strategy-drawer", "description-status": "", size: "medium", "description-text": t.drawerDescription, "footer-button-group-options": t.footerButtonGroupOptions, status: t.store.assignStrategyDrawerStatus, "title-text": t.trans("gpt-app-builder.assign-recommendation-strategy") }, on: { cancelOrBackButtonEvent: t.closeDrawer, onCloseEvent: t.closeDrawer, primaryButtonEvent: t.assignStrategy } }, [t.store.assignStrategyDrawerStatus ? e("div", { staticClass: "assign-strategy-drawer-content d-f f-d-c gap-16" }, [e(t.InSelect, { staticClass: "assign-strategy-select", attrs: { id: "assign-strategy-select", "search-status": "", "static-child-position": "bottom right", "button-status": !1, "dynamic-child-position": !1, "label-text": t.trans("ds-steps.recommendation-strategy"), options: t.strategyOptions, "placeholder-text": t.trans("ds-steps.select-strategy"), "skeleton-sizing": { width: 240, height: 42 }, "skeleton-status": t.store.strategiesLoading, state: t.showSelectionError ? "error" : "default", "state-message": t.showSelectionError ? t.trans("ds-steps.select-strategy-tooltip") : "", value: t.selectValue }, on: { select: t.onSelect } }), t.selectedStrategy ? e("div", { key: String(t.selectedStrategy.strategy_id), staticClass: "assign-strategy-detail" }, [e(t.OrgStrategyDetailModal, { attrs: { show: "", "campaign-details-tab-status": t.campaignTabSupported, "footer-status": !1, strategy: t.selectedStrategy } })], 1) : s._e()], 1) : s._e()]);
|
|
7
|
-
}, n = [], i = /* @__PURE__ */ r(
|
|
8
|
-
a,
|
|
9
|
-
o,
|
|
10
|
-
n,
|
|
11
|
-
!1,
|
|
12
|
-
null,
|
|
13
|
-
"afde0449"
|
|
14
|
-
);
|
|
15
|
-
const p = i.exports;
|
|
16
|
-
export {
|
|
17
|
-
p as default
|
|
18
|
-
};
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { defineComponent as S, defineAsyncComponent as w, ref as c, computed as o, watch as v } from "vue";
|
|
2
|
-
import "@useinsider/design-system-organisms/style";
|
|
3
|
-
import _ from "../../../wrappers/WpDrawer.vue.js";
|
|
4
|
-
import { useToaster as D } from "../../../../composables/useToaster.js";
|
|
5
|
-
import { useTranslations as T } from "../../../../composables/useTranslations.js";
|
|
6
|
-
import { URLS as A } from "../../../../enums/extensions/recommendationBlock.js";
|
|
7
|
-
import { ToasterTypeOptions as u } from "../../../../enums/toaster.js";
|
|
8
|
-
import { useRecommendationExtensionStore as E } from "../../../../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
9
|
-
import { buildStrategyInfoBoxProps as O } from "../../../../utils/strategyInfoBox.js";
|
|
10
|
-
import { InSelect as x } from "@useinsider/design-system-vue";
|
|
11
|
-
const V = /* @__PURE__ */ S({
|
|
12
|
-
__name: "AssignStrategyDrawer",
|
|
13
|
-
setup(B) {
|
|
14
|
-
const p = w(
|
|
15
|
-
async () => (await import("@useinsider/design-system-organisms")).OrgStrategyDetailModal
|
|
16
|
-
), r = T(), e = E(), { showToaster: n } = D(), s = c(null), a = c(!1), l = c(!1), m = o(() => e.assignStrategyDrawerStatus ? r("email-editor.assign-strategy-description", { url: A.RECOMMENDATION_STRATEGIES_PANEL_PATH }) : "");
|
|
17
|
-
v(() => e.assignStrategyDrawerStatus, (t) => {
|
|
18
|
-
if (!t)
|
|
19
|
-
return;
|
|
20
|
-
const { strategyId: i } = e.recommendationConfigs;
|
|
21
|
-
s.value = i || null, a.value = !1, l.value = !!window.l10n, e.fetchStrategies().catch(() => {
|
|
22
|
-
n({
|
|
23
|
-
type: u.Error,
|
|
24
|
-
message: r("discovery-strategy.error-description")
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
const y = o(() => e.strategies.map((t) => ({
|
|
29
|
-
text: t.name,
|
|
30
|
-
value: t.strategy_id,
|
|
31
|
-
infoBoxProps: O(t, r)
|
|
32
|
-
}))), d = o(() => [{ value: s.value }]), g = o(() => {
|
|
33
|
-
const t = e.strategies.find((i) => String(i.strategy_id) === String(s.value ?? ""));
|
|
34
|
-
return t ? { ...t, fallback_config: null } : null;
|
|
35
|
-
}), f = o(() => ({
|
|
36
|
-
primaryButton: {
|
|
37
|
-
styling: "solid",
|
|
38
|
-
type: "primary",
|
|
39
|
-
labelText: r("products.assign-btn")
|
|
40
|
-
},
|
|
41
|
-
cancelOrBackButton: {
|
|
42
|
-
styling: "ghost",
|
|
43
|
-
type: "secondary",
|
|
44
|
-
labelText: r("products.cancel")
|
|
45
|
-
}
|
|
46
|
-
}));
|
|
47
|
-
return { __sfc: !0, OrgStrategyDetailModal: p, trans: r, store: e, showToaster: n, selectedStrategyId: s, showSelectionError: a, campaignTabSupported: l, drawerDescription: m, strategyOptions: y, selectValue: d, selectedStrategy: g, footerButtonGroupOptions: f, closeDrawer: () => {
|
|
48
|
-
e.closeAssignStrategyDrawer();
|
|
49
|
-
}, assignStrategy: () => {
|
|
50
|
-
const t = g.value;
|
|
51
|
-
if (!t) {
|
|
52
|
-
a.value = !0;
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
e.assignStrategy(t), n({
|
|
56
|
-
type: u.Success,
|
|
57
|
-
message: r("email-editor.strategy-assigned-success", { strategyName: t.name })
|
|
58
|
-
}), e.closeAssignStrategyDrawer();
|
|
59
|
-
}, onSelect: (t) => {
|
|
60
|
-
s.value = t.value, a.value = !1;
|
|
61
|
-
}, WpDrawer: _, InSelect: x };
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
export {
|
|
65
|
-
V as default
|
|
66
|
-
};
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
var d = Object.defineProperty;
|
|
2
|
-
var y = (r, s, t) => s in r ? d(r, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[s] = t;
|
|
3
|
-
var o = (r, s, t) => y(r, typeof s != "symbol" ? s + "" : s, t);
|
|
4
|
-
import { ACADEMY_LINKS as m } from "../../../../../enums/academy.js";
|
|
5
|
-
import { CommonControl as h } from "../../../common-control.js";
|
|
6
|
-
import { useRecommendationExtensionStore as u } from "../../store/recommendation.js";
|
|
7
|
-
const p = "recommendation-strategy-control";
|
|
8
|
-
class f extends h {
|
|
9
|
-
constructor() {
|
|
10
|
-
super(...arguments);
|
|
11
|
-
o(this, "store", u());
|
|
12
|
-
o(this, "storeUnsubscription", () => {
|
|
13
|
-
});
|
|
14
|
-
o(this, "listeners", []);
|
|
15
|
-
// The store subscription fires on EVERY mutation of a store six controls
|
|
16
|
-
// share, so the last painted state is kept to skip the DOM work.
|
|
17
|
-
o(this, "lastPaintedState", null);
|
|
18
|
-
}
|
|
19
|
-
getId() {
|
|
20
|
-
return p;
|
|
21
|
-
}
|
|
22
|
-
getTemplate() {
|
|
23
|
-
const t = this.api.translate(
|
|
24
|
-
"You can assign a recommendation strategy by selecting an existing one or creating a new one to show specific content."
|
|
25
|
-
), e = this.api.translate("For more information, you can"), a = this.api.translate("visit Academy");
|
|
26
|
-
return `
|
|
27
|
-
<div class="strategy-control-container">
|
|
28
|
-
<div class="strategy-control-header">
|
|
29
|
-
<h3 class="strategy-control-title">${this.api.translate("Recommendation Strategy")}</h3>
|
|
30
|
-
</div>
|
|
31
|
-
<div class="strategy-control-description-row">
|
|
32
|
-
<p class="strategy-control-description">
|
|
33
|
-
${t}
|
|
34
|
-
${e}
|
|
35
|
-
<a
|
|
36
|
-
href="${m.EMAIL_RECOMMENDATION_BLOCK}"
|
|
37
|
-
target="_blank"
|
|
38
|
-
rel="noopener noreferrer">${a}</a>.
|
|
39
|
-
</p>
|
|
40
|
-
</div>
|
|
41
|
-
<div data-strategy-empty-state>
|
|
42
|
-
${this._GuTwoColumns([
|
|
43
|
-
this._GuButton({
|
|
44
|
-
name: "assignStrategy",
|
|
45
|
-
label: this.api.translate("Assign Strategy"),
|
|
46
|
-
id: "guido__btn-assign-strategy",
|
|
47
|
-
className: "strategy-control-cta on"
|
|
48
|
-
}),
|
|
49
|
-
// Create round-trip ships with SD-149916; until then the CTA
|
|
50
|
-
// stays inert at full contrast, as the design draws it.
|
|
51
|
-
this._GuButton({
|
|
52
|
-
name: "createStrategy",
|
|
53
|
-
label: this.api.translate("Create New Strategy"),
|
|
54
|
-
id: "guido__btn-create-strategy",
|
|
55
|
-
className: "strategy-control-cta primary",
|
|
56
|
-
disabled: !0
|
|
57
|
-
})
|
|
58
|
-
], "strategy-control-cta-row")}
|
|
59
|
-
</div>
|
|
60
|
-
<div data-strategy-assigned-state style="display: none;">
|
|
61
|
-
<div class="strategy-control-name-band">
|
|
62
|
-
<span class="strategy-control-name" data-strategy-name></span>
|
|
63
|
-
</div>
|
|
64
|
-
<div class="strategy-control-actions">
|
|
65
|
-
${this._strategyAction({
|
|
66
|
-
id: "guido__btn-change-strategy",
|
|
67
|
-
label: this.api.translate("Change"),
|
|
68
|
-
modifier: "change"
|
|
69
|
-
})}
|
|
70
|
-
${this._strategyAction({
|
|
71
|
-
id: "guido__btn-remove-strategy",
|
|
72
|
-
label: this.api.translate("Remove"),
|
|
73
|
-
modifier: "remove"
|
|
74
|
-
})}
|
|
75
|
-
</div>
|
|
76
|
-
</div>
|
|
77
|
-
</div>
|
|
78
|
-
`;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Change / Remove are icon+text actions in the design, not buttons — and
|
|
82
|
-
* `ue-button` cannot pair a caption with an arbitrary icon, so these are
|
|
83
|
-
* plain elements. Click wiring is by id, which works on any element.
|
|
84
|
-
*
|
|
85
|
-
* The icon is a CSS mask, not inline SVG: Stripo re-creates the control's
|
|
86
|
-
* markup through Angular, which rebuilds `<svg>` outside the SVG namespace
|
|
87
|
-
* (the view-box attribute comes back lowercased) and it never paints.
|
|
88
|
-
*/
|
|
89
|
-
_strategyAction({ id: t, label: e, modifier: a }) {
|
|
90
|
-
return `
|
|
91
|
-
<button
|
|
92
|
-
id="${t}"
|
|
93
|
-
type="button"
|
|
94
|
-
class="strategy-control-action strategy-control-action--${a}">
|
|
95
|
-
<span>${e}</span>
|
|
96
|
-
</button>
|
|
97
|
-
`;
|
|
98
|
-
}
|
|
99
|
-
onRender() {
|
|
100
|
-
this._teardown(), this._setupButtonListeners(), this._renderState(), this.storeUnsubscription = this.store.$subscribe(() => {
|
|
101
|
-
this._renderState();
|
|
102
|
-
}), this.store.recommendationConfigs.strategyId && !this.store.strategies.length && this.store.fetchStrategies().catch(() => {
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
onDestroy() {
|
|
106
|
-
this._teardown();
|
|
107
|
-
}
|
|
108
|
-
_teardown() {
|
|
109
|
-
this.storeUnsubscription(), this.storeUnsubscription = () => {
|
|
110
|
-
}, this.lastPaintedState = null, this.listeners.forEach(({ element: t, handler: e }) => t.removeEventListener("click", e)), this.listeners = [];
|
|
111
|
-
}
|
|
112
|
-
_setupButtonListeners() {
|
|
113
|
-
const t = this.getContainer();
|
|
114
|
-
if (!t)
|
|
115
|
-
return;
|
|
116
|
-
const e = (a, n) => {
|
|
117
|
-
const i = t.querySelector(a);
|
|
118
|
-
i && (i.addEventListener("click", n), this.listeners.push({ element: i, handler: n }));
|
|
119
|
-
};
|
|
120
|
-
e("#guido__btn-assign-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-remove-strategy", () => this.store.removeStrategy());
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Toggles empty vs assigned state from the store's current block config.
|
|
124
|
-
* Display name comes from the listing; falls back to the raw id while the
|
|
125
|
-
* listing loads (or when the strategy is no longer listed).
|
|
126
|
-
*/
|
|
127
|
-
_renderState() {
|
|
128
|
-
var l;
|
|
129
|
-
const { strategyId: t } = this.store.recommendationConfigs, e = t ? ((l = this.store.assignedStrategy) == null ? void 0 : l.name) ?? "" : "", a = `${t}\0${e}`;
|
|
130
|
-
if (a === this.lastPaintedState)
|
|
131
|
-
return;
|
|
132
|
-
const n = this.getContainer();
|
|
133
|
-
if (!n)
|
|
134
|
-
return;
|
|
135
|
-
const i = n.querySelector("[data-strategy-empty-state]"), c = n.querySelector("[data-strategy-assigned-state]"), g = n.querySelector("[data-strategy-name]");
|
|
136
|
-
!i || !c || (i.style.display = t ? "none" : "", c.style.display = t ? "" : "none", g && t && (g.textContent = e || `#${t}`), this.lastPaintedState = a);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
export {
|
|
140
|
-
p as STRATEGY_CONTROL_ID,
|
|
141
|
-
f as StrategyControl
|
|
142
|
-
};
|
package/dist/src/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import '@useinsider/design-system-organisms/style';
|
|
2
|
-
declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
|
|
3
|
-
export default _default;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { CommonControl } from '../../../common-control';
|
|
2
|
-
export declare const STRATEGY_CONTROL_ID = "recommendation-strategy-control";
|
|
3
|
-
export declare class StrategyControl extends CommonControl {
|
|
4
|
-
private store;
|
|
5
|
-
private storeUnsubscription;
|
|
6
|
-
private listeners;
|
|
7
|
-
private lastPaintedState;
|
|
8
|
-
getId(): string;
|
|
9
|
-
getTemplate(): string;
|
|
10
|
-
/**
|
|
11
|
-
* Change / Remove are icon+text actions in the design, not buttons — and
|
|
12
|
-
* `ue-button` cannot pair a caption with an arbitrary icon, so these are
|
|
13
|
-
* plain elements. Click wiring is by id, which works on any element.
|
|
14
|
-
*
|
|
15
|
-
* The icon is a CSS mask, not inline SVG: Stripo re-creates the control's
|
|
16
|
-
* markup through Angular, which rebuilds `<svg>` outside the SVG namespace
|
|
17
|
-
* (the view-box attribute comes back lowercased) and it never paints.
|
|
18
|
-
*/
|
|
19
|
-
private _strategyAction;
|
|
20
|
-
onRender(): void;
|
|
21
|
-
onDestroy(): void;
|
|
22
|
-
private _teardown;
|
|
23
|
-
private _setupButtonListeners;
|
|
24
|
-
/**
|
|
25
|
-
* Toggles empty vs assigned state from the store's current block config.
|
|
26
|
-
* Display name comes from the listing; falls back to the raw id while the
|
|
27
|
-
* listing loads (or when the strategy is no longer listed).
|
|
28
|
-
*/
|
|
29
|
-
private _renderState;
|
|
30
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
export declare const MOCK_RRS_STRATEGIES: ({
|
|
2
|
-
strategy_id: number;
|
|
3
|
-
name: string;
|
|
4
|
-
status: string;
|
|
5
|
-
suitable_channels: string;
|
|
6
|
-
suitable_page_types: string;
|
|
7
|
-
algorithm: string;
|
|
8
|
-
algorithm_used: string;
|
|
9
|
-
method: string;
|
|
10
|
-
size: number;
|
|
11
|
-
filters: string;
|
|
12
|
-
shuffle: number;
|
|
13
|
-
attribute_affinity: number;
|
|
14
|
-
exclude_view: number;
|
|
15
|
-
exclude_purchase: number;
|
|
16
|
-
exclude_cart: number;
|
|
17
|
-
manual_merchandising_products: string;
|
|
18
|
-
fallback_config: null;
|
|
19
|
-
channelNames: string;
|
|
20
|
-
campaignCount: {
|
|
21
|
-
active: number;
|
|
22
|
-
passive: number;
|
|
23
|
-
test: number;
|
|
24
|
-
};
|
|
25
|
-
created_at: string;
|
|
26
|
-
updated_at: string;
|
|
27
|
-
last_updated_by: string;
|
|
28
|
-
mixed_strategies?: undefined;
|
|
29
|
-
exclude_view_duration?: undefined;
|
|
30
|
-
exclude_view_duration_type?: undefined;
|
|
31
|
-
} | {
|
|
32
|
-
strategy_id: number;
|
|
33
|
-
name: string;
|
|
34
|
-
status: string;
|
|
35
|
-
suitable_channels: string;
|
|
36
|
-
suitable_page_types: string;
|
|
37
|
-
algorithm: string;
|
|
38
|
-
algorithm_used: string;
|
|
39
|
-
mixed_strategies: string;
|
|
40
|
-
method: string;
|
|
41
|
-
size: number;
|
|
42
|
-
filters: string;
|
|
43
|
-
shuffle: number;
|
|
44
|
-
attribute_affinity: number;
|
|
45
|
-
exclude_view: number;
|
|
46
|
-
exclude_view_duration: number;
|
|
47
|
-
exclude_view_duration_type: string;
|
|
48
|
-
exclude_purchase: number;
|
|
49
|
-
exclude_cart: number;
|
|
50
|
-
manual_merchandising_products: string;
|
|
51
|
-
fallback_config: null;
|
|
52
|
-
channelNames: string;
|
|
53
|
-
campaignCount: {
|
|
54
|
-
active: number;
|
|
55
|
-
passive: number;
|
|
56
|
-
test: number;
|
|
57
|
-
};
|
|
58
|
-
created_at: string;
|
|
59
|
-
updated_at: string;
|
|
60
|
-
last_updated_by: string;
|
|
61
|
-
})[];
|
|
62
|
-
declare const _default: import("msw").HttpHandler[];
|
|
63
|
-
export default _default;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { RrsStrategy } from '@@/Types/recommendation';
|
|
2
|
-
import { useTranslations } from '@@/Composables/useTranslations';
|
|
3
|
-
export declare const STRATEGY_INFO_BOX_CLASS = "assign-strategy-info-box";
|
|
4
|
-
/**
|
|
5
|
-
* Props for the design system info box that previews a strategy on hover.
|
|
6
|
-
*
|
|
7
|
-
* The box is InSelect's own per-option feature: the dropdown v-binds this whole
|
|
8
|
-
* object onto `<in-info-box>`, so `titleText`/`descriptionText` are all it takes
|
|
9
|
-
* — no slot component. Both go through the design system's sanitizer, and every
|
|
10
|
-
* partner-supplied value is escaped here before it reaches that markup.
|
|
11
|
-
*
|
|
12
|
-
* `trans` is injectable because callers map this over a whole listing, and
|
|
13
|
-
* `useTranslations()` rebuilds its dictionary and memo cache on every call.
|
|
14
|
-
*/
|
|
15
|
-
export declare const buildStrategyInfoBoxProps: (strategy: RrsStrategy, trans?: ReturnType<typeof useTranslations>) => {
|
|
16
|
-
id: string;
|
|
17
|
-
theme: string;
|
|
18
|
-
variant: string;
|
|
19
|
-
className: string;
|
|
20
|
-
titleText: string;
|
|
21
|
-
descriptionText: string;
|
|
22
|
-
};
|