@useinsider/guido 3.18.0 → 3.18.1-beta.636c82d
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/components/Guido.vue.js +1 -1
- package/dist/components/Guido.vue2.js +86 -82
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +13 -11
- package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +72 -56
- package/dist/components/organisms/header/EditorActions.vue.js +1 -1
- package/dist/components/organisms/header/EditorActions.vue2.js +54 -41
- package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +20 -18
- package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +21 -0
- package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +46 -0
- package/dist/composables/useActionsApi.js +82 -67
- package/dist/composables/useAutoSave.js +31 -26
- package/dist/composables/useEditorLock.js +20 -0
- package/dist/composables/useGuidoStateBridge.js +37 -31
- package/dist/composables/useSave.js +42 -39
- package/dist/enums/extensions/recommendationBlock.js +38 -31
- package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +35 -31
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +129 -68
- package/dist/guido.css +1 -1
- package/dist/package.json.js +1 -1
- package/dist/src/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.d.ts +2 -0
- package/dist/src/composables/useEditorLock.d.ts +10 -0
- package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +1 -0
- package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +49 -0
- package/dist/src/stores/onboarding.d.ts +377 -0
- package/dist/static/styles/components/recommendation-strategy.css.js +21 -4
- package/dist/stores/onboarding.js +41 -36
- package/package.json +2 -2
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import { useTranslations as
|
|
2
|
-
const
|
|
1
|
+
import { useTranslations as n } from "../../composables/useTranslations.js";
|
|
2
|
+
const o = {
|
|
3
3
|
RECOMMENDATION_API_URL: "https://recommendationv2.api.useinsider.com",
|
|
4
4
|
// Relative path → same-origin as the embedding inone dashboard.
|
|
5
5
|
PRODUCT_ATTRIBUTES_PATH: "/product-attributes/get-attributes",
|
|
6
6
|
RECOMMENDATION_STRATEGIES_PATH: "/api/recommendation-strategies",
|
|
7
|
-
RECOMMENDATION_STRATEGIES_PANEL_PATH: "/discovery/recommendation-strategies"
|
|
8
|
-
|
|
7
|
+
RECOMMENDATION_STRATEGIES_PANEL_PATH: "/discovery/recommendation-strategies",
|
|
8
|
+
// Smart Recommender hides the Email channel unless the URL asks for it, so a strategy created
|
|
9
|
+
// without this flag can never be Email-suitable and would never reach the editor's list.
|
|
10
|
+
RECOMMENDATION_STRATEGY_CREATE_PATH: "/discovery/recommendation-strategies/create?isEmail=true"
|
|
11
|
+
}, d = (e) => {
|
|
12
|
+
const { RECOMMENDATION_STRATEGIES_PANEL_PATH: r } = o;
|
|
13
|
+
return `${r}/${e}/edit`;
|
|
14
|
+
}, m = {
|
|
9
15
|
CLIENT_ID: "clientId"
|
|
10
|
-
},
|
|
11
|
-
const e =
|
|
16
|
+
}, p = () => {
|
|
17
|
+
const e = n();
|
|
12
18
|
return [
|
|
13
19
|
{
|
|
14
20
|
id: 11,
|
|
@@ -71,14 +77,14 @@ const l = {
|
|
|
71
77
|
path: "top-sellers"
|
|
72
78
|
}
|
|
73
79
|
];
|
|
74
|
-
},
|
|
80
|
+
}, v = ["discount", "omnibus_price", "omnibus_discount", "price", "original_price"], h = [
|
|
75
81
|
{ text: "before the amount", value: "0" },
|
|
76
82
|
{ text: "after the amount", value: "1" }
|
|
77
|
-
],
|
|
83
|
+
], x = [
|
|
78
84
|
{ text: "dot(.)", value: "." },
|
|
79
85
|
{ text: "comma(,)", value: "," },
|
|
80
86
|
{ text: "space( )", value: " " }
|
|
81
|
-
],
|
|
87
|
+
], b = [
|
|
82
88
|
{ text: "0", value: "0" },
|
|
83
89
|
{ text: "1", value: "1" },
|
|
84
90
|
{ text: "2", value: "2" },
|
|
@@ -90,54 +96,55 @@ const l = {
|
|
|
90
96
|
{ text: "contains", value: "~" },
|
|
91
97
|
{ text: "does not contain", value: "!~" },
|
|
92
98
|
{ text: "any of", value: a }
|
|
93
|
-
],
|
|
99
|
+
], s = [
|
|
94
100
|
{ text: "is exactly", value: "=" },
|
|
95
101
|
{ text: "is not exactly", value: "!==" },
|
|
96
102
|
{ text: "contains", value: "~" },
|
|
97
103
|
{ text: "does not contain", value: "!~" },
|
|
98
104
|
{ text: "any of", value: a }
|
|
99
|
-
],
|
|
105
|
+
], i = [
|
|
100
106
|
{ text: "is equal to", value: "=" },
|
|
101
107
|
{ text: "is greater than", value: ">" },
|
|
102
108
|
{ text: "is less than", value: "<" }
|
|
103
|
-
],
|
|
109
|
+
], u = [
|
|
104
110
|
{ text: "is equal to", value: "=" },
|
|
105
111
|
{ text: "after", value: ">" },
|
|
106
112
|
{ text: "before", value: "<" }
|
|
107
|
-
],
|
|
113
|
+
], c = [
|
|
108
114
|
{ text: "true", value: "==" },
|
|
109
115
|
{ text: "false", value: "!=" }
|
|
110
|
-
],
|
|
116
|
+
], g = (e) => {
|
|
111
117
|
if (!e)
|
|
112
118
|
return t;
|
|
113
119
|
switch (e) {
|
|
114
120
|
case "Boolean":
|
|
115
|
-
return
|
|
121
|
+
return c;
|
|
116
122
|
case "Date":
|
|
117
|
-
return
|
|
123
|
+
return u;
|
|
118
124
|
case "Number":
|
|
119
|
-
return
|
|
125
|
+
return i;
|
|
120
126
|
case "String":
|
|
121
127
|
return t;
|
|
122
128
|
case "Strings":
|
|
123
|
-
return
|
|
129
|
+
return s;
|
|
124
130
|
default:
|
|
125
131
|
return t;
|
|
126
132
|
}
|
|
127
133
|
};
|
|
128
134
|
export {
|
|
129
135
|
a as OP_ANY_OF,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
t as operatorOptionsForStrings
|
|
136
|
+
v as PriceAttributes,
|
|
137
|
+
m as QUERY_PARAMS,
|
|
138
|
+
o as URLS,
|
|
139
|
+
b as currencyDecimalCounts,
|
|
140
|
+
h as currencyLocationMaps,
|
|
141
|
+
x as currencyOperators,
|
|
142
|
+
g as getOperatorOptions,
|
|
143
|
+
p as getRecommendationFeedSourceMaps,
|
|
144
|
+
s as operatorOptionsForArrayOfStrings,
|
|
145
|
+
c as operatorOptionsForBooleans,
|
|
146
|
+
u as operatorOptionsForDates,
|
|
147
|
+
i as operatorOptionsForNumbers,
|
|
148
|
+
t as operatorOptionsForStrings,
|
|
149
|
+
d as strategyEditPath
|
|
143
150
|
};
|
|
@@ -1,26 +1,28 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { ACADEMY_LINKS as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
var m = Object.defineProperty;
|
|
2
|
+
var h = (o, a, t) => a in o ? m(o, a, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[a] = t;
|
|
3
|
+
var r = (o, a, t) => h(o, typeof a != "symbol" ? a + "" : a, t);
|
|
4
|
+
import { ACADEMY_LINKS as p } from "../../../../../enums/academy.js";
|
|
5
|
+
import { useOnboardingStore as u } from "../../../../../stores/onboarding.js";
|
|
6
|
+
import { CommonControl as S } from "../../../common-control.js";
|
|
7
|
+
import { useRecommendationExtensionStore as _ } from "../../store/recommendation.js";
|
|
8
|
+
const b = "recommendation-strategy-control";
|
|
9
|
+
class w extends S {
|
|
9
10
|
constructor() {
|
|
10
11
|
super(...arguments);
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
r(this, "store", _());
|
|
13
|
+
r(this, "onboardingStore", u());
|
|
14
|
+
r(this, "storeUnsubscription", () => {
|
|
13
15
|
});
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
r(this, "listeners", []);
|
|
17
|
+
r(this, "lastPaintedState", null);
|
|
16
18
|
}
|
|
17
19
|
getId() {
|
|
18
|
-
return
|
|
20
|
+
return b;
|
|
19
21
|
}
|
|
20
22
|
getTemplate() {
|
|
21
23
|
const t = this.api.translate(
|
|
22
24
|
"You can assign a recommendation strategy by selecting an existing one or creating a new one to show specific content."
|
|
23
|
-
), e = this.api.translate("For more information, you can"),
|
|
25
|
+
), e = this.api.translate("For more information, you can"), s = this.api.translate("visit Academy");
|
|
24
26
|
return `
|
|
25
27
|
<div class="strategy-control-container">
|
|
26
28
|
<div class="strategy-control-header">
|
|
@@ -31,9 +33,9 @@ class f extends h {
|
|
|
31
33
|
${t}
|
|
32
34
|
${e}
|
|
33
35
|
<a
|
|
34
|
-
href="${
|
|
36
|
+
href="${p.EMAIL_RECOMMENDATION_BLOCK}"
|
|
35
37
|
target="_blank"
|
|
36
|
-
rel="noopener noreferrer">${
|
|
38
|
+
rel="noopener noreferrer">${s}</a>.
|
|
37
39
|
</p>
|
|
38
40
|
</div>
|
|
39
41
|
<div data-strategy-empty-state>
|
|
@@ -48,14 +50,14 @@ class f extends h {
|
|
|
48
50
|
name: "createStrategy",
|
|
49
51
|
label: this.api.translate("Create New Strategy"),
|
|
50
52
|
id: "guido__btn-create-strategy",
|
|
51
|
-
className: "strategy-control-cta primary"
|
|
52
|
-
disabled: !0
|
|
53
|
+
className: "strategy-control-cta primary"
|
|
53
54
|
})
|
|
54
55
|
], "strategy-control-cta-row")}
|
|
55
56
|
</div>
|
|
56
57
|
<div data-strategy-assigned-state style="display: none;">
|
|
57
58
|
<div class="strategy-control-name-band">
|
|
58
59
|
<span class="strategy-control-name" data-strategy-name></span>
|
|
60
|
+
<span class="strategy-control-name-skeleton" data-strategy-name-skeleton></span>
|
|
59
61
|
</div>
|
|
60
62
|
<div class="strategy-control-actions">
|
|
61
63
|
${this._strategyAction({
|
|
@@ -73,12 +75,12 @@ class f extends h {
|
|
|
73
75
|
</div>
|
|
74
76
|
`;
|
|
75
77
|
}
|
|
76
|
-
_strategyAction({ id: t, label: e, modifier:
|
|
78
|
+
_strategyAction({ id: t, label: e, modifier: s }) {
|
|
77
79
|
return `
|
|
78
80
|
<button
|
|
79
81
|
id="${t}"
|
|
80
82
|
type="button"
|
|
81
|
-
class="strategy-control-action strategy-control-action--${
|
|
83
|
+
class="strategy-control-action strategy-control-action--${s}">
|
|
82
84
|
<span>${e}</span>
|
|
83
85
|
</button>
|
|
84
86
|
`;
|
|
@@ -88,6 +90,8 @@ class f extends h {
|
|
|
88
90
|
this._renderState();
|
|
89
91
|
}), this.store.recommendationConfigs.strategyId && !this.store.strategies.length && this.store.fetchStrategies().catch(() => {
|
|
90
92
|
});
|
|
93
|
+
const t = this.store.currentRecommendationId;
|
|
94
|
+
t !== null && !!this.store.blockStates[t] && !this.store.recommendationConfigs.strategyId && this.onboardingStore.startOnboarding("recommendationStrategyOnboarding");
|
|
91
95
|
}
|
|
92
96
|
onDestroy() {
|
|
93
97
|
this._teardown();
|
|
@@ -100,25 +104,25 @@ class f extends h {
|
|
|
100
104
|
const t = this.getContainer();
|
|
101
105
|
if (!t)
|
|
102
106
|
return;
|
|
103
|
-
const e = (
|
|
104
|
-
const
|
|
105
|
-
|
|
107
|
+
const e = (s, i) => {
|
|
108
|
+
const n = t.querySelector(s);
|
|
109
|
+
n && (n.addEventListener("click", i), this.listeners.push({ element: n, handler: i }));
|
|
106
110
|
};
|
|
107
|
-
e("#guido__btn-assign-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-change-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-remove-strategy", () => this.store.openRemoveStrategyModal());
|
|
111
|
+
e("#guido__btn-assign-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-create-strategy", () => this.store.openStrategyCreation()), e("#guido__btn-change-strategy", () => this.store.openAssignStrategyDrawer()), e("#guido__btn-remove-strategy", () => this.store.openRemoveStrategyModal());
|
|
108
112
|
}
|
|
109
113
|
_renderState() {
|
|
110
|
-
var
|
|
111
|
-
const { strategyId: t } = this.store.recommendationConfigs, e = t ? ((
|
|
112
|
-
if (
|
|
114
|
+
var y;
|
|
115
|
+
const { strategyId: t } = this.store.recommendationConfigs, e = t ? ((y = this.store.assignedStrategy) == null ? void 0 : y.name) ?? "" : "", s = !!t && !e && this.store.strategiesLoading, i = `${t}\0${e}\0${s}`;
|
|
116
|
+
if (i === this.lastPaintedState)
|
|
113
117
|
return;
|
|
114
118
|
const n = this.getContainer();
|
|
115
119
|
if (!n)
|
|
116
120
|
return;
|
|
117
|
-
const
|
|
118
|
-
!
|
|
121
|
+
const l = n.querySelector("[data-strategy-empty-state]"), g = n.querySelector("[data-strategy-assigned-state]"), c = n.querySelector("[data-strategy-name]"), d = n.querySelector("[data-strategy-name-skeleton]");
|
|
122
|
+
!l || !g || (l.style.display = t ? "none" : "", g.style.display = t ? "" : "none", c && (c.style.display = s ? "none" : "", t && !s && (c.textContent = e || `#${t}`)), d && (d.style.display = s ? "" : "none"), this.lastPaintedState = i);
|
|
119
123
|
}
|
|
120
124
|
}
|
|
121
125
|
export {
|
|
122
|
-
|
|
123
|
-
|
|
126
|
+
b as STRATEGY_CONTROL_ID,
|
|
127
|
+
w as StrategyControl
|
|
124
128
|
};
|
|
@@ -1,22 +1,31 @@
|
|
|
1
|
-
import { getRecommendationFeedSourceMaps as
|
|
2
|
-
import { useRecommendationApi as
|
|
3
|
-
import { useConfigStore as
|
|
4
|
-
import {
|
|
1
|
+
import { getRecommendationFeedSourceMaps as C, strategyEditPath as _, URLS as D, getOperatorOptions as L, PriceAttributes as N } from "../../../../enums/extensions/recommendationBlock.js";
|
|
2
|
+
import { useRecommendationApi as U } from "../../../../services/recommendationApi.js";
|
|
3
|
+
import { useConfigStore as E } from "../../../../stores/config.js";
|
|
4
|
+
import { asText as w } from "../../../../utils/genericUtil.js";
|
|
5
|
+
import { defineStore as A } from "pinia";
|
|
5
6
|
import "../constants/selectors.js";
|
|
6
|
-
import { DEFAULT_MOBILE_CARDS_IN_ROW as
|
|
7
|
-
import { DEFAULT_NODE_CONFIG as
|
|
8
|
-
import { getDefaultProducts as
|
|
9
|
-
import { generateCompleteFilterQuery as
|
|
10
|
-
import { getPartnerRecommendationParams as
|
|
11
|
-
import { sanitizeProductIds as
|
|
12
|
-
import { isFilterValid as
|
|
13
|
-
import { isConfigValid as
|
|
14
|
-
const
|
|
15
|
-
let
|
|
16
|
-
const
|
|
17
|
-
|
|
7
|
+
import { DEFAULT_MOBILE_CARDS_IN_ROW as x, DEFAULT_CARDS_IN_ROW as B } from "../constants/layout.js";
|
|
8
|
+
import { DEFAULT_NODE_CONFIG as M, EXCLUDED_ALGORITHM_IDS as T } from "../constants/defaultConfig.js";
|
|
9
|
+
import { getDefaultProducts as v } from "../templates/utils.js";
|
|
10
|
+
import { generateCompleteFilterQuery as G } from "../utils/filterUtil.js";
|
|
11
|
+
import { getPartnerRecommendationParams as O } from "../utils/partnerCustomizations.js";
|
|
12
|
+
import { sanitizeProductIds as z } from "../utils/productIds.js";
|
|
13
|
+
import { isFilterValid as V } from "../validation/filterSchema.js";
|
|
14
|
+
import { isConfigValid as $ } from "../validation/requiredFields.js";
|
|
15
|
+
const d = U();
|
|
16
|
+
let g = null, h = null, S = null, p = null, I = 0;
|
|
17
|
+
const b = /* @__PURE__ */ new Map();
|
|
18
|
+
let u = null, y = null;
|
|
19
|
+
const j = (t, e) => {
|
|
20
|
+
const r = t.filter((s) => !e.has(String(s.strategy_id)));
|
|
21
|
+
if (!r.length)
|
|
22
|
+
return null;
|
|
23
|
+
const n = r.reduce((s, i) => w(i.created_at) > w(s.created_at) ? i : s);
|
|
24
|
+
return String(n.strategy_id);
|
|
25
|
+
};
|
|
26
|
+
function P() {
|
|
18
27
|
return {
|
|
19
|
-
cardsInRow:
|
|
28
|
+
cardsInRow: B,
|
|
20
29
|
currencySettings: {
|
|
21
30
|
name: "USD",
|
|
22
31
|
value: "USD",
|
|
@@ -30,7 +39,7 @@ function w() {
|
|
|
30
39
|
productIds: [],
|
|
31
40
|
id: 1,
|
|
32
41
|
language: "en_US",
|
|
33
|
-
mobileCardsInRow:
|
|
42
|
+
mobileCardsInRow: x,
|
|
34
43
|
mobileLayoutEnabled: !1,
|
|
35
44
|
orientation: "grid",
|
|
36
45
|
recommendedProducts: [],
|
|
@@ -46,9 +55,9 @@ function w() {
|
|
|
46
55
|
priceHideIfSameAsDiscounted: !1
|
|
47
56
|
};
|
|
48
57
|
}
|
|
49
|
-
function
|
|
58
|
+
function F() {
|
|
50
59
|
return {
|
|
51
|
-
recommendationConfigs:
|
|
60
|
+
recommendationConfigs: P(),
|
|
52
61
|
recommendationProducts: [],
|
|
53
62
|
filterStatus: !1,
|
|
54
63
|
filterSelectionDrawerStatus: !1,
|
|
@@ -59,7 +68,7 @@ function C() {
|
|
|
59
68
|
filterSnapshot: null
|
|
60
69
|
};
|
|
61
70
|
}
|
|
62
|
-
const
|
|
71
|
+
const q = () => ({
|
|
63
72
|
recommendationCampaignUrls: {},
|
|
64
73
|
activePredictiveAlgorithms: [],
|
|
65
74
|
languages: {},
|
|
@@ -68,11 +77,13 @@ const z = () => ({
|
|
|
68
77
|
strategies: [],
|
|
69
78
|
strategiesLoading: !1,
|
|
70
79
|
strategyUrlTemplates: {},
|
|
80
|
+
lastCreatedStrategyId: null,
|
|
81
|
+
strategiesFetched: !1,
|
|
71
82
|
blockStates: {},
|
|
72
83
|
currentRecommendationId: null,
|
|
73
84
|
configVersion: 0
|
|
74
|
-
}),
|
|
75
|
-
state: () =>
|
|
85
|
+
}), st = A("guidoRecommendationExtension", {
|
|
86
|
+
state: () => q(),
|
|
76
87
|
getters: {
|
|
77
88
|
// ====================================================================
|
|
78
89
|
// Proxy Getters — Backward Compatible Access to Current Block State
|
|
@@ -82,7 +93,7 @@ const z = () => ({
|
|
|
82
93
|
* This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
|
|
83
94
|
*/
|
|
84
95
|
recommendationConfigs(t) {
|
|
85
|
-
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs :
|
|
96
|
+
return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : P();
|
|
86
97
|
},
|
|
87
98
|
/**
|
|
88
99
|
* Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
|
|
@@ -137,8 +148,8 @@ const z = () => ({
|
|
|
137
148
|
return [...new Set(t.map((e) => e.filterGroup))].sort((e, r) => e - r);
|
|
138
149
|
},
|
|
139
150
|
getActivePredictiveAlgorithms: (t) => {
|
|
140
|
-
const e =
|
|
141
|
-
return t.activePredictiveAlgorithms.filter((n) => !
|
|
151
|
+
const e = C(), r = [];
|
|
152
|
+
return t.activePredictiveAlgorithms.filter((n) => !T.includes(n)).forEach((n) => {
|
|
142
153
|
r.push(...e.filter((s) => s.id === n));
|
|
143
154
|
}), r.map((n) => ({
|
|
144
155
|
text: n.name,
|
|
@@ -156,7 +167,7 @@ const z = () => ({
|
|
|
156
167
|
getFilterList() {
|
|
157
168
|
return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
|
|
158
169
|
let e;
|
|
159
|
-
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` :
|
|
170
|
+
return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : N.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
|
|
160
171
|
text: t.displayName,
|
|
161
172
|
value: e,
|
|
162
173
|
type: t.attributeType
|
|
@@ -178,7 +189,7 @@ const z = () => ({
|
|
|
178
189
|
setCurrentBlock(t) {
|
|
179
190
|
this.blockStates[t] || (this.blockStates = {
|
|
180
191
|
...this.blockStates,
|
|
181
|
-
[t]:
|
|
192
|
+
[t]: F()
|
|
182
193
|
}), this.currentRecommendationId = t;
|
|
183
194
|
},
|
|
184
195
|
/**
|
|
@@ -246,7 +257,7 @@ const z = () => ({
|
|
|
246
257
|
decimalCount: String(e.currencyDecimalCount),
|
|
247
258
|
decimalSeparator: r(e.currencyDecimalSeparator, ","),
|
|
248
259
|
thousandSeparator: r(e.currencyThousandSeparator, ".")
|
|
249
|
-
}, s = !this.blockStates[t], i = s ?
|
|
260
|
+
}, s = !this.blockStates[t], i = s ? F() : this.blockStates[t];
|
|
250
261
|
i.recommendationConfigs = {
|
|
251
262
|
...i.recommendationConfigs,
|
|
252
263
|
strategy: e.strategy,
|
|
@@ -285,7 +296,7 @@ const z = () => ({
|
|
|
285
296
|
* Creates a filter with the first available attribute and operator pre-selected.
|
|
286
297
|
*/
|
|
287
298
|
createDefaultFilter(t, e) {
|
|
288
|
-
const [r] = this.getFilterList, [n] =
|
|
299
|
+
const [r] = this.getFilterList, [n] = L(r == null ? void 0 : r.type);
|
|
289
300
|
return {
|
|
290
301
|
type: "standardFilter",
|
|
291
302
|
attribute: (r == null ? void 0 : r.value) ?? "",
|
|
@@ -345,29 +356,79 @@ const z = () => ({
|
|
|
345
356
|
this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId] || (this.blockStates[this.currentRecommendationId].removeStrategyModalStatus = !1);
|
|
346
357
|
},
|
|
347
358
|
async fetchStrategies() {
|
|
348
|
-
if (
|
|
349
|
-
await S;
|
|
359
|
+
if (p && await p, this.strategiesFetched)
|
|
350
360
|
return;
|
|
351
|
-
|
|
352
|
-
|
|
361
|
+
const t = I;
|
|
362
|
+
p = (async () => {
|
|
353
363
|
this.strategiesLoading = !0;
|
|
354
364
|
try {
|
|
355
|
-
|
|
365
|
+
const e = await d.fetchRecommendationStrategies();
|
|
366
|
+
if (t !== I)
|
|
367
|
+
return;
|
|
368
|
+
if (this.strategies = e, this.strategiesFetched = !0, y) {
|
|
369
|
+
const r = j(e, y);
|
|
370
|
+
r && (this.lastCreatedStrategyId = r), y = new Set(e.map((n) => String(n.strategy_id)));
|
|
371
|
+
}
|
|
356
372
|
} finally {
|
|
357
373
|
this.strategiesLoading = !1;
|
|
358
374
|
}
|
|
359
375
|
})();
|
|
360
376
|
try {
|
|
361
|
-
await
|
|
377
|
+
await p;
|
|
362
378
|
} finally {
|
|
363
|
-
|
|
379
|
+
p = null;
|
|
364
380
|
}
|
|
365
381
|
},
|
|
382
|
+
invalidateStrategies() {
|
|
383
|
+
this.strategiesFetched = !1, I += 1;
|
|
384
|
+
},
|
|
385
|
+
/**
|
|
386
|
+
* Opens a Smart Recommender strategy page in a new tab and refreshes the list every time
|
|
387
|
+
* the user comes back. `visibilitychange` covers the tab case; `focus` covers the page
|
|
388
|
+
* landing in a separate window, where this document never goes hidden.
|
|
389
|
+
*
|
|
390
|
+
* Deliberately NOT one-shot: the strategy tab stays open, so a user can create a second
|
|
391
|
+
* strategy in it and come back again — a listener that disarmed on the first return would
|
|
392
|
+
* leave that one missing from the list. Armed only once the user actually opens a strategy
|
|
393
|
+
* page, so anyone who never does pays nothing.
|
|
394
|
+
*/
|
|
395
|
+
_armStrategyPageReturn(t) {
|
|
396
|
+
window.open(t, "_blank", "noopener"), u == null || u();
|
|
397
|
+
let e = !1;
|
|
398
|
+
const r = () => {
|
|
399
|
+
document.hidden || e || (e = !0, this.invalidateStrategies(), this.fetchStrategies().catch(() => {
|
|
400
|
+
}).finally(() => {
|
|
401
|
+
e = !1;
|
|
402
|
+
}));
|
|
403
|
+
};
|
|
404
|
+
document.addEventListener("visibilitychange", r), window.addEventListener("focus", r), u = () => {
|
|
405
|
+
document.removeEventListener("visibilitychange", r), window.removeEventListener("focus", r), u = null;
|
|
406
|
+
};
|
|
407
|
+
},
|
|
408
|
+
/** Lets the editor tear the return listeners down when it unmounts. */
|
|
409
|
+
disposeStrategyPageReturn() {
|
|
410
|
+
u == null || u(), y = null;
|
|
411
|
+
},
|
|
412
|
+
/**
|
|
413
|
+
* Opens Smart Recommender's strategy creation page. Every return refreshes the list, and any
|
|
414
|
+
* strategy that appeared since the page was opened is remembered so the drawer preselects it —
|
|
415
|
+
* including a second one created without ever closing that tab.
|
|
416
|
+
*/
|
|
417
|
+
openStrategyCreation() {
|
|
418
|
+
y = new Set(this.strategies.map((t) => String(t.strategy_id))), this._armStrategyPageReturn(D.RECOMMENDATION_STRATEGY_CREATE_PATH);
|
|
419
|
+
},
|
|
420
|
+
/**
|
|
421
|
+
* Opens the strategy's edit page. Every return refreshes the list so the block reflects the
|
|
422
|
+
* edited configuration; nothing is preselected because the strategy is already assigned.
|
|
423
|
+
*/
|
|
424
|
+
openStrategyEdit(t) {
|
|
425
|
+
this._armStrategyPageReturn(_(t));
|
|
426
|
+
},
|
|
366
427
|
async resolveStrategyUrlTemplate(t, e) {
|
|
367
428
|
const r = typeof t.updated_at == "string" ? t.updated_at : "", n = r ? `${t.strategy_id}:${r}:${e}` : "", s = n ? this.strategyUrlTemplates[n] : void 0;
|
|
368
429
|
if (s)
|
|
369
430
|
return s;
|
|
370
|
-
const { full_path: i = "" } = await
|
|
431
|
+
const { full_path: i = "" } = await d.generateStrategyEndpoint(t, e) ?? {};
|
|
371
432
|
return n && i && (this.strategyUrlTemplates = {
|
|
372
433
|
...this.strategyUrlTemplates,
|
|
373
434
|
[n]: i
|
|
@@ -380,23 +441,23 @@ const z = () => ({
|
|
|
380
441
|
});
|
|
381
442
|
},
|
|
382
443
|
removeStrategy() {
|
|
383
|
-
this.patchCurrentBlockConfig({ strategyId: "", size:
|
|
444
|
+
this.patchCurrentBlockConfig({ strategyId: "", size: M.size });
|
|
384
445
|
},
|
|
385
446
|
// ====================================================================
|
|
386
447
|
// Shared Data Fetching (fetched once, used by all blocks)
|
|
387
448
|
// ====================================================================
|
|
388
449
|
async fetchRecommendationCreateData() {
|
|
389
450
|
if (!this.activePredictiveAlgorithms.length) {
|
|
390
|
-
if (
|
|
391
|
-
await
|
|
451
|
+
if (g) {
|
|
452
|
+
await g;
|
|
392
453
|
return;
|
|
393
454
|
}
|
|
394
|
-
|
|
455
|
+
g = (async () => {
|
|
395
456
|
const {
|
|
396
457
|
activePredictiveAlgorithms: t,
|
|
397
458
|
languages: e,
|
|
398
459
|
currencies: r
|
|
399
|
-
} = await
|
|
460
|
+
} = await d.fetchRecommendationCreateData();
|
|
400
461
|
if (this.activePredictiveAlgorithms = t, this.languages = e, this.currentRecommendationId !== null && this.blockStates[this.currentRecommendationId]) {
|
|
401
462
|
const n = this.blockStates[this.currentRecommendationId];
|
|
402
463
|
n.filterStatus = !!n.recommendationConfigs.filters.length;
|
|
@@ -404,9 +465,9 @@ const z = () => ({
|
|
|
404
465
|
this.currencyList = r;
|
|
405
466
|
})();
|
|
406
467
|
try {
|
|
407
|
-
await
|
|
468
|
+
await g;
|
|
408
469
|
} finally {
|
|
409
|
-
|
|
470
|
+
g = null;
|
|
410
471
|
}
|
|
411
472
|
}
|
|
412
473
|
},
|
|
@@ -417,7 +478,7 @@ const z = () => ({
|
|
|
417
478
|
return;
|
|
418
479
|
}
|
|
419
480
|
h = (async () => {
|
|
420
|
-
const t = await
|
|
481
|
+
const t = await d.fetchRecommendationFilters();
|
|
421
482
|
this.filterList = t;
|
|
422
483
|
})();
|
|
423
484
|
try {
|
|
@@ -452,7 +513,7 @@ const z = () => ({
|
|
|
452
513
|
const n = [...e.recommendationConfigs.filters];
|
|
453
514
|
n[r] = {
|
|
454
515
|
...t,
|
|
455
|
-
isValid:
|
|
516
|
+
isValid: V(t)
|
|
456
517
|
}, e.recommendationConfigs.filters = n;
|
|
457
518
|
}
|
|
458
519
|
},
|
|
@@ -490,7 +551,7 @@ const z = () => ({
|
|
|
490
551
|
}), e.recommendationConfigs.filters = r;
|
|
491
552
|
},
|
|
492
553
|
generateFilterQuery() {
|
|
493
|
-
return
|
|
554
|
+
return G(this.recommendationConfigs.filters);
|
|
494
555
|
},
|
|
495
556
|
/**
|
|
496
557
|
* Validation-only check invoked at save-CTA time. Defined as an action
|
|
@@ -498,33 +559,33 @@ const z = () => ({
|
|
|
498
559
|
* every block's recommendationConfigs across user edits.
|
|
499
560
|
*/
|
|
500
561
|
hasInvalidBlock() {
|
|
501
|
-
return Object.values(this.blockStates).some((t) =>
|
|
562
|
+
return Object.values(this.blockStates).some((t) => !$(t.recommendationConfigs, this));
|
|
502
563
|
},
|
|
503
564
|
// ====================================================================
|
|
504
565
|
// Per-Block Product Fetching
|
|
505
566
|
// ====================================================================
|
|
506
567
|
async fetchRecommendationProducts() {
|
|
507
568
|
if (!(this.currentRecommendationId === null || !this.blockStates[this.currentRecommendationId])) {
|
|
508
|
-
if (
|
|
509
|
-
await
|
|
569
|
+
if (S) {
|
|
570
|
+
await S;
|
|
510
571
|
return;
|
|
511
572
|
}
|
|
512
|
-
|
|
573
|
+
S = this._doFetchProducts();
|
|
513
574
|
try {
|
|
514
|
-
await
|
|
575
|
+
await S;
|
|
515
576
|
} finally {
|
|
516
|
-
|
|
577
|
+
S = null;
|
|
517
578
|
}
|
|
518
579
|
}
|
|
519
580
|
},
|
|
520
581
|
async _doFetchProducts() {
|
|
521
|
-
var
|
|
522
|
-
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n =
|
|
582
|
+
var f;
|
|
583
|
+
const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = E();
|
|
523
584
|
if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
|
|
524
585
|
await this._doFetchStrategyProducts(t);
|
|
525
586
|
return;
|
|
526
587
|
}
|
|
527
|
-
const s = r.filters.filter((m) => m.isValid), i =
|
|
588
|
+
const s = r.filters.filter((m) => m.isValid), i = G(s), o = ((f = C().find((m) => m.key === r.strategy)) == null ? void 0 : f.path) || "", c = parseInt(r.size) || 6, a = {
|
|
528
589
|
locale: r.language,
|
|
529
590
|
currency: r.currencySettings.value,
|
|
530
591
|
partnerName: n.partnerName,
|
|
@@ -532,21 +593,21 @@ const z = () => ({
|
|
|
532
593
|
details: !0,
|
|
533
594
|
campaignId: n.variationId
|
|
534
595
|
};
|
|
535
|
-
r.strategy === "manualMerchandising" ? a.productId =
|
|
596
|
+
r.strategy === "manualMerchandising" ? a.productId = z(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), i && (a.filter = i), r.shuffleProducts && (a.shuffle = !0), Object.assign(
|
|
536
597
|
a,
|
|
537
|
-
|
|
598
|
+
O(n.partnerName, r.strategy)
|
|
538
599
|
);
|
|
539
600
|
let l;
|
|
540
601
|
try {
|
|
541
|
-
l = await
|
|
602
|
+
l = await d.fetchRecommendationProducts(o, a);
|
|
542
603
|
} catch {
|
|
543
604
|
l = [];
|
|
544
605
|
}
|
|
545
606
|
this._setBlockProducts(t, l, c);
|
|
546
607
|
},
|
|
547
608
|
async _doFetchStrategyProducts(t) {
|
|
548
|
-
const e = (
|
|
549
|
-
|
|
609
|
+
const e = (b.get(t) ?? 0) + 1;
|
|
610
|
+
b.set(t, e);
|
|
550
611
|
const { recommendationConfigs: r } = this.blockStates[t];
|
|
551
612
|
let n = [], s = parseInt(r.size) || 6;
|
|
552
613
|
try {
|
|
@@ -556,25 +617,25 @@ const z = () => ({
|
|
|
556
617
|
);
|
|
557
618
|
if (i) {
|
|
558
619
|
s = parseInt(String(i.size ?? "")) || s;
|
|
559
|
-
const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"),
|
|
560
|
-
|
|
620
|
+
const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), f = l === -1 ? a : a.slice(0, l), m = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((k) => k && !k.startsWith("user_id=")), R = m.length ? `${f}?${m.join("&")}` : f;
|
|
621
|
+
R && (n = await d.fetchRecommendationProductsByUrl(R));
|
|
561
622
|
}
|
|
562
623
|
} catch {
|
|
563
624
|
n = [];
|
|
564
625
|
}
|
|
565
|
-
|
|
626
|
+
b.get(t) === e && this._setBlockProducts(t, n, s);
|
|
566
627
|
},
|
|
567
628
|
_setBlockProducts(t, e, r) {
|
|
568
629
|
if (!this.blockStates[t])
|
|
569
630
|
return;
|
|
570
|
-
const n = e.length > 0 ? e :
|
|
631
|
+
const n = e.length > 0 ? e : v(r);
|
|
571
632
|
this.blockStates[t].recommendationProducts = [
|
|
572
633
|
...n.slice(0, r),
|
|
573
|
-
...
|
|
634
|
+
...v(Math.max(0, r - n.length))
|
|
574
635
|
];
|
|
575
636
|
}
|
|
576
637
|
}
|
|
577
638
|
});
|
|
578
639
|
export {
|
|
579
|
-
|
|
640
|
+
st as useRecommendationExtensionStore
|
|
580
641
|
};
|