@useinsider/guido 3.12.0-beta.840207a → 3.12.0-beta.86e34da
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/dist/@types/config/schemas.js +6 -6
- package/dist/components/organisms/email-preview/desktop-preview/DesktopPreview.vue.js +1 -1
- package/dist/components/organisms/email-preview/desktop-preview/DesktopPreview.vue2.js +8 -8
- package/dist/components/organisms/email-preview/mobile-preview/ContentView.vue.js +5 -5
- package/dist/components/organisms/email-preview/mobile-preview/ContentView.vue2.js +10 -10
- package/dist/components/organisms/extensions/recommendation/StrategyDetailDrawer.vue.js +8 -6
- package/dist/components/organisms/extensions/recommendation/StrategyDetailDrawer.vue2.js +98 -71
- package/dist/composables/usePreviewInteractionGuard.js +36 -11
- package/dist/composables/useRecommendation.js +63 -78
- package/dist/composables/useRecommendationPreview.js +61 -60
- package/dist/enums/extensions/filteringV2.js +1017 -1
- package/dist/enums/extensions/recommendationBlock.js +34 -19
- package/dist/extensions/Blocks/Recommendation/constants/controlIds.js +1 -1
- package/dist/extensions/Blocks/Recommendation/controls/blockBackground/index.js +10 -0
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +24 -20
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +245 -106
- package/dist/extensions/Blocks/Recommendation/extension.js +23 -21
- package/dist/extensions/Blocks/Recommendation/iconsRegistry.js +17 -3
- package/dist/extensions/Blocks/Recommendation/recommendation.css.js +257 -0
- package/dist/extensions/Blocks/Recommendation/settingsPanel.js +41 -40
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +310 -117
- package/dist/extensions/Blocks/Recommendation/utils/strategyNavigation.js +8 -0
- package/dist/extensions/Blocks/Recommendation/utils/strategySummary.js +93 -8
- package/dist/extensions/Blocks/Recommendation/utils/strategyUrl.js +43 -0
- package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +18 -16
- package/dist/extensions/Blocks/Unsubscribe/utils/constants.js +3 -2
- package/dist/extensions/Blocks/common-control.js +2 -1
- package/dist/extensions/Blocks/controlFactories.js +125 -75
- package/dist/guido.css +1 -1
- package/dist/services/recommendationApi.js +90 -45
- package/dist/services/stripoApi.js +18 -18
- package/dist/src/@types/config/schemas.d.ts +2 -2
- package/dist/src/composables/usePreviewInteractionGuard.d.ts +1 -1
- package/dist/src/enums/extensions/recommendationBlock.d.ts +25 -2
- package/dist/src/extensions/Blocks/Recommendation/constants/controlIds.d.ts +1 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/blockBackground/index.d.ts +14 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/index.d.ts +1 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +7 -3
- package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +59 -45
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +301 -4
- package/dist/src/extensions/Blocks/Recommendation/utils/strategyNavigation.d.ts +10 -0
- package/dist/src/extensions/Blocks/Recommendation/utils/strategyUrl.d.ts +51 -0
- package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +5 -0
- package/dist/src/extensions/Blocks/Unsubscribe/utils/constants.d.ts +1 -0
- package/dist/src/extensions/Blocks/common-control.d.ts +2 -1
- package/dist/src/extensions/Blocks/controlFactories.d.ts +36 -0
- package/dist/src/mock/api/recommendation-strategies.d.ts +2 -0
- package/dist/src/services/recommendationApi.d.ts +3 -1
- package/dist/src/utils/urlSchemes.d.ts +6 -0
- package/dist/static/styles/base.css.js +0 -15
- package/dist/static/styles/components/base-input.css.js +6 -7
- package/dist/utils/templatePreparation.js +56 -47
- package/dist/utils/urlSchemes.js +4 -0
- package/package.json +1 -1
|
@@ -1,71 +1,102 @@
|
|
|
1
|
-
import { useHttp as
|
|
2
|
-
import { QUERY_PARAMS as
|
|
3
|
-
const
|
|
4
|
-
if (Array.isArray(
|
|
5
|
-
return
|
|
6
|
-
const
|
|
7
|
-
return Array.isArray(
|
|
8
|
-
},
|
|
9
|
-
(
|
|
10
|
-
attributeName:
|
|
11
|
-
attributeJs:
|
|
12
|
-
attributeType:
|
|
13
|
-
type:
|
|
14
|
-
displayName:
|
|
15
|
-
isFilterable:
|
|
16
|
-
},
|
|
1
|
+
import { useHttp as l } from "../composables/useHttp.js";
|
|
2
|
+
import { URLS as i, RRS_STRATEGIES_MAX_PAGES as f, QUERY_PARAMS as d, RRS_STRATEGIES_PER_PAGE as E, RRS_EMAIL_ACTIVE_FILTER as y } from "../enums/extensions/recommendationBlock.js";
|
|
3
|
+
const S = (r) => {
|
|
4
|
+
if (Array.isArray(r))
|
|
5
|
+
return r;
|
|
6
|
+
const c = !!r && typeof r == "object" && "data" in r, a = r == null ? void 0 : r.data;
|
|
7
|
+
return Array.isArray(a) ? a : (r && (!c || a != null) && console.error("[Guido] Unexpected RRS payload shape, falling back to empty:", Object.keys(r)), []);
|
|
8
|
+
}, g = (r) => !r || typeof r != "object" ? null : "data" in r ? r.data ?? null : Object.keys(r).length ? r : null, T = (r) => r.reduce(
|
|
9
|
+
(c, a, m) => (c[m] = {
|
|
10
|
+
attributeName: a.attributeName,
|
|
11
|
+
attributeJs: a.attributeJs,
|
|
12
|
+
attributeType: a.attributeType,
|
|
13
|
+
type: a.type,
|
|
14
|
+
displayName: a.displayName,
|
|
15
|
+
isFilterable: a.isFilterable
|
|
16
|
+
}, c),
|
|
17
17
|
{}
|
|
18
|
-
),
|
|
19
|
-
const { get:
|
|
18
|
+
), O = () => {
|
|
19
|
+
const { get: r, post: c } = l(), { get: a } = l({ headers: {} }), m = "6KcLM9TwheVB1mgK";
|
|
20
20
|
return {
|
|
21
|
+
duplicateStrategy: async (e) => {
|
|
22
|
+
try {
|
|
23
|
+
const { data: o } = await c(
|
|
24
|
+
i.STRATEGY_DUPLICATE_PATH.replace("{{id}}", e)
|
|
25
|
+
), t = g(o) ?? o;
|
|
26
|
+
return !(t != null && t.strategyId) || t.status === !1 ? null : String(t.strategyId);
|
|
27
|
+
} catch (o) {
|
|
28
|
+
return console.error("duplicateStrategy error:", o), null;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
21
31
|
fetchRecommendationCreateData: async () => {
|
|
22
32
|
try {
|
|
23
|
-
return (await
|
|
33
|
+
return (await r("/newsletter/recommendations/create-data")).data;
|
|
24
34
|
} catch (e) {
|
|
25
35
|
throw console.error("fetchRecommendationCreateData error:", e), e;
|
|
26
36
|
}
|
|
27
37
|
},
|
|
28
38
|
fetchRecommendationFilters: async () => {
|
|
29
39
|
try {
|
|
30
|
-
const { data: e } = await
|
|
31
|
-
|
|
40
|
+
const { data: e } = await r(
|
|
41
|
+
i.PRODUCT_ATTRIBUTES_PATH
|
|
32
42
|
), o = Array.isArray(e) ? e : (e == null ? void 0 : e.data) ?? [];
|
|
33
|
-
return
|
|
43
|
+
return T(o);
|
|
34
44
|
} catch (e) {
|
|
35
45
|
throw console.error("fetchRecommendationFilters error:", e), e;
|
|
36
46
|
}
|
|
37
47
|
},
|
|
38
48
|
fetchRecommendationProducts: async (e, o) => {
|
|
39
|
-
var
|
|
49
|
+
var t;
|
|
40
50
|
try {
|
|
41
51
|
const n = new URLSearchParams(Object.entries(o));
|
|
42
|
-
n.set(
|
|
43
|
-
const
|
|
44
|
-
console.debug("🏁 Recommendation API Query:",
|
|
45
|
-
const
|
|
46
|
-
`${
|
|
52
|
+
n.set(d.CLIENT_ID, m);
|
|
53
|
+
const u = decodeURIComponent(n.toString());
|
|
54
|
+
console.debug("🏁 Recommendation API Query:", u);
|
|
55
|
+
const s = await a(
|
|
56
|
+
`${i.RECOMMENDATION_API_URL}/v2/${e}?${u}`
|
|
47
57
|
);
|
|
48
|
-
return ((
|
|
58
|
+
return ((t = s == null ? void 0 : s.data) == null ? void 0 : t.data) ?? [];
|
|
49
59
|
} catch (n) {
|
|
50
60
|
throw console.error("fetchRecommendationProducts error:", n), n;
|
|
51
61
|
}
|
|
52
62
|
},
|
|
63
|
+
fetchRecommendationProductsByUrl: async (e) => {
|
|
64
|
+
var o;
|
|
65
|
+
try {
|
|
66
|
+
const t = await a(e);
|
|
67
|
+
return ((o = t == null ? void 0 : t.data) == null ? void 0 : o.data) ?? [];
|
|
68
|
+
} catch (t) {
|
|
69
|
+
throw console.error("fetchRecommendationProductsByUrl error:", t), t;
|
|
70
|
+
}
|
|
71
|
+
},
|
|
53
72
|
fetchRecommendationStrategies: async () => {
|
|
54
73
|
try {
|
|
55
|
-
const e =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
74
|
+
const e = [], o = /* @__PURE__ */ new Set();
|
|
75
|
+
for (let t = 1; t <= f; t++) {
|
|
76
|
+
const n = new URLSearchParams({
|
|
77
|
+
[d.FILTERS]: y,
|
|
78
|
+
[d.PER_PAGE]: String(E),
|
|
79
|
+
[d.PAGE]: String(t)
|
|
80
|
+
}), { data: u } = await r(
|
|
81
|
+
`${i.RECOMMENDATION_STRATEGIES_PATH}?${n.toString()}`
|
|
82
|
+
), s = S(u), A = o.size;
|
|
83
|
+
if (s.forEach((R) => {
|
|
84
|
+
const h = String(R.strategy_id);
|
|
85
|
+
o.has(h) || (o.add(h), e.push(R));
|
|
86
|
+
}), s.length < E || o.size === A)
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
return e;
|
|
59
90
|
} catch (e) {
|
|
60
91
|
throw console.error("fetchRecommendationStrategies error:", e), e;
|
|
61
92
|
}
|
|
62
93
|
},
|
|
63
94
|
fetchStrategyCampaigns: async (e, o) => {
|
|
64
95
|
try {
|
|
65
|
-
const { data:
|
|
66
|
-
`${
|
|
96
|
+
const { data: t } = await r(
|
|
97
|
+
`${i.RECOMMENDATION_STRATEGIES_PATH}/${e}/campaigns`
|
|
67
98
|
);
|
|
68
|
-
return
|
|
99
|
+
return S(t).map((n) => ({
|
|
69
100
|
id: n.id,
|
|
70
101
|
name: n.name,
|
|
71
102
|
status: n.status,
|
|
@@ -74,22 +105,36 @@ const h = (t) => {
|
|
|
74
105
|
productAlias: n.productAlias,
|
|
75
106
|
isPreventing: n.isPreventing
|
|
76
107
|
}));
|
|
77
|
-
} catch (
|
|
78
|
-
return console.error("fetchStrategyCampaigns error:",
|
|
108
|
+
} catch (t) {
|
|
109
|
+
return console.error("fetchStrategyCampaigns error:", t), [];
|
|
79
110
|
}
|
|
80
111
|
},
|
|
81
|
-
|
|
112
|
+
generateStrategyEndpoint: async (e, o) => {
|
|
82
113
|
try {
|
|
83
|
-
const
|
|
84
|
-
|
|
114
|
+
const t = {
|
|
115
|
+
campaignId: o,
|
|
116
|
+
// Email has no page types (RecommendationStrategyEnums::NON_PAGE_TYPE_CHANNELS),
|
|
117
|
+
// so this stays empty rather than splitting an empty string into [''].
|
|
118
|
+
pageTypes: [],
|
|
119
|
+
isPreviewer: !1,
|
|
120
|
+
strategy: e,
|
|
121
|
+
// Resolved per recipient at send time, never here.
|
|
122
|
+
userId: ""
|
|
123
|
+
}, { data: n } = await c(
|
|
124
|
+
i.STRATEGY_ENDPOINT_GENERATE_PATH,
|
|
125
|
+
t
|
|
85
126
|
);
|
|
86
|
-
return
|
|
87
|
-
} catch (
|
|
88
|
-
|
|
127
|
+
return g(n);
|
|
128
|
+
} catch (t) {
|
|
129
|
+
console.error("generateStrategyEndpoint error:", t);
|
|
130
|
+
const n = t == null ? void 0 : t.status;
|
|
131
|
+
if (typeof n == "number" && n >= 400 && n < 500)
|
|
132
|
+
return null;
|
|
133
|
+
throw t;
|
|
89
134
|
}
|
|
90
135
|
}
|
|
91
136
|
};
|
|
92
137
|
};
|
|
93
138
|
export {
|
|
94
|
-
|
|
139
|
+
O as useRecommendationApi
|
|
95
140
|
};
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { useHttp as
|
|
2
|
-
import { useToaster as
|
|
3
|
-
import { MAX_DEFAULT_TEMPLATE_ID as
|
|
4
|
-
import { useBlankTemplate as
|
|
5
|
-
const
|
|
6
|
-
|
|
1
|
+
import { useHttp as m } from "../composables/useHttp.js";
|
|
2
|
+
import { useToaster as y } from "../composables/useToaster.js";
|
|
3
|
+
import { MAX_DEFAULT_TEMPLATE_ID as f } from "../enums/defaults.js";
|
|
4
|
+
import { useBlankTemplate as g } from "./blankTemplate.js";
|
|
5
|
+
const l = () => ({
|
|
6
|
+
id: 0,
|
|
7
|
+
stripoId: 0,
|
|
8
|
+
unsubscriptionPreferencePages: []
|
|
9
|
+
}), D = () => {
|
|
10
|
+
const { get: s, post: u } = m(), { handleError: r } = y(), { getBlankTemplate: n } = g();
|
|
7
11
|
return {
|
|
8
12
|
getToken: async () => {
|
|
9
13
|
try {
|
|
@@ -26,13 +30,13 @@ const D = () => {
|
|
|
26
30
|
},
|
|
27
31
|
getDefaultTemplate: async () => {
|
|
28
32
|
try {
|
|
29
|
-
const t = new URLSearchParams(window.location.search), e = t.get("default-template"),
|
|
30
|
-
if (!i && !
|
|
31
|
-
return await
|
|
32
|
-
const
|
|
33
|
-
return !a || typeof a != "object" || !("html" in a) || !("css" in a) ? await
|
|
33
|
+
const t = new URLSearchParams(window.location.search), e = t.get("default-template"), p = t.get("master"), o = e ? parseInt(e) : 0, i = o >= 1 && o <= f ? o : 0;
|
|
34
|
+
if (!i && !p)
|
|
35
|
+
return await n();
|
|
36
|
+
const d = `/stripo/default-template/${i}`, { data: c } = await s(d), a = typeof c == "string" ? JSON.parse(c) : c;
|
|
37
|
+
return !a || typeof a != "object" || !("html" in a) || !("css" in a) ? await n() : a;
|
|
34
38
|
} catch (t) {
|
|
35
|
-
return r(t, "Failed to fetch default template"),
|
|
39
|
+
return r(t, "Failed to fetch default template"), n();
|
|
36
40
|
}
|
|
37
41
|
},
|
|
38
42
|
getSyncModulesStatus: async () => {
|
|
@@ -53,13 +57,9 @@ const D = () => {
|
|
|
53
57
|
getSyncModule: async (t) => {
|
|
54
58
|
try {
|
|
55
59
|
const { data: e } = await s(`/stripo/stripo-modules/${t}/get`);
|
|
56
|
-
return e;
|
|
60
|
+
return Array.isArray(e == null ? void 0 : e.unsubscriptionPreferencePages) ? e : l();
|
|
57
61
|
} catch (e) {
|
|
58
|
-
return r(e, "Failed to get sync module"),
|
|
59
|
-
id: 0,
|
|
60
|
-
stripoId: 0,
|
|
61
|
-
unsubscriptionPreferencePages: []
|
|
62
|
-
};
|
|
62
|
+
return r(e, "Failed to get sync module"), l();
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
setSyncModuleUnsubscriptionPages: async (t) => {
|
|
@@ -381,7 +381,7 @@ export declare const FeaturesSchema: v.ObjectSchema<{
|
|
|
381
381
|
* Select a Reusable Recommendation Strategy (RRS) instead of a per-block algorithm.
|
|
382
382
|
* Replaces the algorithm dropdown with a strategy dropdown fed from Smart Recommender.
|
|
383
383
|
*/
|
|
384
|
-
readonly reusableRecommendationStrategy: v.OptionalSchema<v.BooleanSchema<undefined>,
|
|
384
|
+
readonly reusableRecommendationStrategy: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
|
|
385
385
|
}, undefined>;
|
|
386
386
|
/**
|
|
387
387
|
* Default block types available in Stripo
|
|
@@ -773,7 +773,7 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
|
|
|
773
773
|
* Select a Reusable Recommendation Strategy (RRS) instead of a per-block algorithm.
|
|
774
774
|
* Replaces the algorithm dropdown with a strategy dropdown fed from Smart Recommender.
|
|
775
775
|
*/
|
|
776
|
-
readonly reusableRecommendationStrategy: v.OptionalSchema<v.BooleanSchema<undefined>,
|
|
776
|
+
readonly reusableRecommendationStrategy: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
|
|
777
777
|
}, undefined>, {}>;
|
|
778
778
|
/** Block configuration */
|
|
779
779
|
readonly blocks: v.OptionalSchema<v.ObjectSchema<{
|
|
@@ -4,13 +4,36 @@ export declare const URLS: {
|
|
|
4
4
|
RECOMMENDATION_API_URL: string;
|
|
5
5
|
PRODUCT_ATTRIBUTES_PATH: string;
|
|
6
6
|
RECOMMENDATION_STRATEGIES_PATH: string;
|
|
7
|
-
|
|
7
|
+
STRATEGY_ENDPOINT_GENERATE_PATH: string;
|
|
8
|
+
STRATEGY_DUPLICATE_PATH: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Smart Recommender panel routes, relative to the embedding inone origin.
|
|
12
|
+
* Guido navigates in the same tab; the flow continues on those pages and does
|
|
13
|
+
* not come back (`{{id}}` is substituted by `buildStrategyEditPath`).
|
|
14
|
+
*/
|
|
15
|
+
export declare const STRATEGY_PAGES: {
|
|
16
|
+
LISTING: string;
|
|
17
|
+
CREATE: string;
|
|
18
|
+
EDIT: string;
|
|
8
19
|
};
|
|
9
20
|
export declare const QUERY_PARAMS: {
|
|
10
21
|
CLIENT_ID: string;
|
|
11
|
-
STRATEGY_ID: string;
|
|
12
22
|
FILTERS: string;
|
|
23
|
+
PAGE: string;
|
|
24
|
+
PER_PAGE: string;
|
|
13
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* Page size for the strategy listing.
|
|
28
|
+
*
|
|
29
|
+
* Sent explicitly because Smart Recommender's default page size is not documented
|
|
30
|
+
* anywhere we can read: an unpaginated call would silently return only the first
|
|
31
|
+
* page and the marketer would see a short list with no error. The caller pages
|
|
32
|
+
* until a short page comes back.
|
|
33
|
+
*/
|
|
34
|
+
export declare const RRS_STRATEGIES_PER_PAGE = 100;
|
|
35
|
+
/** Safety stop for the listing pager, mirroring discovery-strategies-fe's helper. */
|
|
36
|
+
export declare const RRS_STRATEGIES_MAX_PAGES = 50;
|
|
14
37
|
/**
|
|
15
38
|
* Smart Recommender's filter grammar: `[table.field][operator][value]`, ANDed with `*`.
|
|
16
39
|
* `~` means "contains" — required because `suitable_channels` is a comma-separated
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* These IDs are returned by the getId() method of each control
|
|
4
4
|
*/
|
|
5
5
|
export declare enum RecommendationControlId {
|
|
6
|
+
BLOCK_BACKGROUND = "recommendation-block-background-color-control",
|
|
6
7
|
BUTTON_ALIGN = "recommendation-block-button-align-control",
|
|
7
8
|
BUTTON_BORDER = "recommendation-block-button-border-control",
|
|
8
9
|
BUTTON_BORDER_RADIUS = "recommendation-block-button-border-radius-control",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const BlockBackgroundColorControl: {
|
|
2
|
+
new (): {
|
|
3
|
+
getId(): string;
|
|
4
|
+
getLabels(): {
|
|
5
|
+
title: string;
|
|
6
|
+
};
|
|
7
|
+
getTargetNodes(root: import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode): import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode[];
|
|
8
|
+
getAdditionalModifications(root: import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode): import("@stripoinc/ui-editor-extensions").TemplateModifier<import("@stripoinc/ui-editor-extensions").HtmlNodeModifier, import("@stripoinc/ui-editor-extensions").CssNodeModifier> | undefined;
|
|
9
|
+
getParentControlId(): string;
|
|
10
|
+
api: import("@stripoinc/ui-editor-extensions").ControlApi;
|
|
11
|
+
getModificationDescription(): import("@stripoinc/ui-editor-extensions").ModificationDescription | undefined;
|
|
12
|
+
isVisible(_node: import("@stripoinc/ui-editor-extensions").ImmutableHtmlNode): boolean;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -20,6 +20,7 @@ export { ButtonControls } from './button';
|
|
|
20
20
|
export { ImageControls } from './image';
|
|
21
21
|
export { CustomAttributeControls } from './customAttribute';
|
|
22
22
|
export { SpacingControl, SPACING_CONTROL_ID } from './spacing';
|
|
23
|
+
export { BlockBackgroundColorControl } from './blockBackground';
|
|
23
24
|
export { CardBackgroundColorControl, CARD_BACKGROUND_COLOR_CONTROL_ID } from './cardBackground';
|
|
24
25
|
export { RecommendationCardCompositionControl, COMPOSITION_CONTROL_BLOCK_ID } from './cardComposition';
|
|
25
26
|
export { SyncInfoMessageControl, SYNC_INFO_MESSAGE_CONTROL_ID } from './syncInfoMessage';
|
|
@@ -109,8 +109,12 @@ export declare class RecommendationBlockControl extends CommonControl {
|
|
|
109
109
|
*/
|
|
110
110
|
private _listenStateUpdates;
|
|
111
111
|
/**
|
|
112
|
-
* Persists the
|
|
113
|
-
*
|
|
112
|
+
* Persists the Pinia-owned parts of the block config to the Stripo node config,
|
|
113
|
+
* so they survive template save/reload cycles.
|
|
114
|
+
*
|
|
115
|
+
* Filters are edited in a drawer and the strategy in an overlaid picker — neither
|
|
116
|
+
* is a Stripo form element, so neither can write to the node itself. Both ride
|
|
117
|
+
* this one update to keep the undo history to a single entry per change.
|
|
114
118
|
*/
|
|
115
|
-
private
|
|
119
|
+
private _persistStoreConfigToNode;
|
|
116
120
|
}
|
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reusable Recommendation Strategy (RRS) Selection Control
|
|
3
|
-
*
|
|
4
|
-
* Lets the marketer pick a named strategy defined in Smart Recommender instead
|
|
5
|
-
* of configuring an algorithm per block. The selected strategy id is stored in
|
|
6
|
-
* node config (persists with the template) and decides the block's
|
|
7
|
-
* recommendation URL at compile time.
|
|
8
|
-
*
|
|
9
|
-
* Rendered only when the `reusableRecommendationStrategy` feature is enabled;
|
|
10
|
-
* otherwise the block keeps using AlgorithmControl.
|
|
11
|
-
*
|
|
12
|
-
* Beside the dropdown sits an icon button that opens the strategy detail drawer.
|
|
13
|
-
* The RRS listing page shows these details in an `InSelect` hover card, which
|
|
14
|
-
* cannot be reproduced here — `_GuSelect` has no `infoBoxProps` equivalent — so
|
|
15
|
-
* the details move out of the 425px panel and over the editor instead.
|
|
16
|
-
*
|
|
17
|
-
* ponytail: selecting a strategy only drives the URL — Number of Products,
|
|
18
|
-
* Locale, Currency and Filters stay independently editable in the panel. The
|
|
19
|
-
* product decision on which of those become strategy-owned is still open
|
|
20
|
-
* (see the Figma "which settings stay in the editor" note), so nothing is
|
|
21
|
-
* locked or overwritten here. Add that only once the decision lands.
|
|
22
|
-
*/
|
|
23
|
-
import type { ImmutableHtmlNode } from '@stripoinc/ui-editor-extensions';
|
|
24
1
|
import { CommonControl } from '../../../common-control';
|
|
25
2
|
export declare const STRATEGY_CONTROL_ID = "recommendation-strategy-control";
|
|
26
3
|
/**
|
|
@@ -28,34 +5,71 @@ export declare const STRATEGY_CONTROL_ID = "recommendation-strategy-control";
|
|
|
28
5
|
*/
|
|
29
6
|
export declare class StrategyControl extends CommonControl {
|
|
30
7
|
private store;
|
|
31
|
-
|
|
32
|
-
|
|
8
|
+
/**
|
|
9
|
+
* InOne's dictionary, not Stripo's. Every dotted key here
|
|
10
|
+
* (`discovery-strategy.*`, `gpt-app-builder.*`) lives in the host panel's
|
|
11
|
+
* translations, which `this.api.translate` does not read — that one is only
|
|
12
|
+
* for the plain-English control labels the rest of this panel uses.
|
|
13
|
+
*/
|
|
14
|
+
private trans;
|
|
15
|
+
private events;
|
|
16
|
+
private unsubscribeStore;
|
|
17
|
+
private searchTerm;
|
|
18
|
+
private isOpen;
|
|
19
|
+
private cardHideTimer;
|
|
33
20
|
getId(): string;
|
|
34
21
|
getTemplate(): string;
|
|
35
22
|
onRender(): void;
|
|
36
23
|
onDestroy(): void;
|
|
37
|
-
|
|
38
|
-
_setFormValues(): void;
|
|
39
|
-
_initializeSelectItems(): void;
|
|
24
|
+
private _root;
|
|
40
25
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
26
|
+
* All listeners are delegated onto nodes that survive `innerHTML` rebuilds and
|
|
27
|
+
* are torn down together by the AbortController — the option rows themselves
|
|
28
|
+
* are replaced on every render and must never own a listener.
|
|
29
|
+
*/
|
|
30
|
+
private _setupEventListeners;
|
|
31
|
+
/**
|
|
32
|
+
* Keeps the trigger label and the gear's enabled state in step with the store.
|
|
43
33
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
|
|
34
|
+
* Both depend on data that arrives after the first render: the strategy listing
|
|
35
|
+
* is fetched asynchronously, and `strategyId` changes when the user picks,
|
|
36
|
+
* duplicates, or switches blocks.
|
|
37
|
+
*/
|
|
38
|
+
private _subscribeToStoreChanges;
|
|
39
|
+
/**
|
|
40
|
+
* Fingerprint of everything the rendered markup depends on.
|
|
48
41
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
42
|
+
* Ids rather than a count: a refetch that renames a strategy or swaps one for
|
|
43
|
+
* another of the same length would otherwise leave the trigger and the card
|
|
44
|
+
* showing stale copy until some unrelated store change happened to repaint.
|
|
45
|
+
*/
|
|
46
|
+
private _stateKey;
|
|
47
|
+
private _render;
|
|
48
|
+
private _renderTrigger;
|
|
49
|
+
private _renderOptions;
|
|
50
|
+
/**
|
|
51
|
+
* Client-side filtering: the listing is fetched whole and cached, so narrowing
|
|
52
|
+
* it here avoids a request per keystroke.
|
|
53
|
+
*/
|
|
54
|
+
private _filteredStrategies;
|
|
55
|
+
private _toggleMenu;
|
|
56
|
+
private _closeMenu;
|
|
57
|
+
/**
|
|
58
|
+
* The hover card is `position: fixed`, so it can sit beside the panel instead of
|
|
59
|
+
* being clipped by it. Placed once per hover — the list cannot scroll under the
|
|
60
|
+
* pointer without the pointer leaving, so there is nothing to keep in sync.
|
|
61
|
+
*/
|
|
62
|
+
private _showCard;
|
|
63
|
+
/** Grace period for the pointer to cross the gap between option and card. */
|
|
64
|
+
private _scheduleHideCard;
|
|
65
|
+
private _cancelHideCard;
|
|
66
|
+
private _hideCard;
|
|
67
|
+
/**
|
|
68
|
+
* Mirrors the design system's `InInfoBox`: coloured top rule, heading +
|
|
69
|
+
* "last updated" details, content, then a divided footer holding the View
|
|
70
|
+
* More text button. The component itself cannot render here, so the markup
|
|
71
|
+
* and the CSS reproduce its structure and tokens rather than approximating
|
|
72
|
+
* them — the values in `recommendation.css` are read from its stylesheet.
|
|
52
73
|
*/
|
|
53
|
-
|
|
54
|
-
_setDisabled(element: string, disabled: boolean): void;
|
|
55
|
-
_showMessage(text: string): void;
|
|
56
|
-
_hideMessage(): void;
|
|
57
|
-
_onDetailsClick(): void;
|
|
58
|
-
_setupDetailsButtonListener(): void;
|
|
59
|
-
_onStrategyChange(value: string): void;
|
|
60
|
-
_listenToFormUpdates(): void;
|
|
74
|
+
private _buildCardHtml;
|
|
61
75
|
}
|